I want to store a hash/JSON data of users in Redis and want to add the user in users hash the user data like this.
For example, users = {};
When user rahul logs in then users will become.
users = {
rahul: {
username: 'rahul',
}
}
And when user namita login then
users = {
rahul: {
username: 'rahul',
},
namita: {
username: 'namita',
}
}
What will the code be to do this in Redis?
How will I initialise the key users and add rahul to it?
Out of this set, hset, etc., which function do I need to use?
And how will I retrieve the data of users['rahul'] via Redis?
Probably the most optimal solution to store single hash/json would be to use hashes commands. I also had this "dilemma" and there are several questions regarding data structure containing users with JSON-like objects in Redis.
EDIT
Use node_redis module. It's actively maintained by a pro a probably the most used node.js driver for Redis. First you should use SADD command to add your new JSON object name into the set in order to track which items "users" contain. Then use HMSET to store "user:rahul" object key-value hashes. Example:
// add first user
client.sadd("users", "user:rahul");
client.hmset("user:rahul", "username", "rahul", "foo", "bar");
// add second user
client.sadd("users", "user:namita");
client.hmset("user:namita", "username", "namita", "foo", "baz");
You can now access your users by various types of redis hash command depending if you want to retrieve only certain hash values or the entire single user object. To get all of the users you can use SMEMBERS command for example. Try to look at the node_redis readme and examples where you should find more information about its API.
Related
What's the best way to save data in db to keep track of a user clicked a like/favorite button or not?
I've tried the following data structure:
postId:{
...
like_count:123,
user_who_liked:[uid1,uid2,uid3...]
}
When the data above is downloaded to the client, we can check if the client liked the post or not by checking if the array user_who_liked contains the client's uid or not. However, if there are more than 1000 items in the user_who_liked array, this approach consumes too much redundant bandwidth.
I found the following json data from instagram:
{
...
viewer_has_liked: false
viewer_has_saved: false
viewer_has_saved_to_collection: false
viewer_in_photo_of_you: false
}
This approach seems more efficient, but how do the database know if the user has liked or not? Do they store a bunch of uids and check if the user's uid is inside it? Are those has_liked/has_saved booleans derived attributes?
I'm trying to create a database (json) with Firebase.
I searched the docs and the net but couldn't find a clear way to start.
I want to have a database of users.
each user (represented as UID) should have a nickname and a list of friends.
I tried making a .json file that looks like this:
{
users:{
}
}
and adding it to the Firebase console to get started but it wouldn't work.
How can I do it?
the database should look like this:
{
users:{
UID:{
nickname: hello
friends: UID2
}
UID2:{
nickname: world
friends: UID
}
}
I don't know if I got that right, so I would really appreciate any help you guys could give me at this subject.
Thanks in advance!
Seems like a good place to start. I would make two changes though.
keep the list is friends separate
keep the friends as a set, instead of a single value or array
keep the list is friends separate
A basic recommendation when using the Firebase Database is to keep your data structure shallow/flat. There are many reasons for this, and you have at least two.
With your current data structure, say that you want to show a list of user names. You can only get that list by listening to /users. And that means you don't just get the user name for each user, but also their list of friends. Chances that you're going to show all that data to the user are minimal, so that means that you've just wasted some of their bandwidth.
Say that you want to allow everyone to read the list of user names. But you only want each user to be able to read their own list of friends. Your current data structure makes that hard, since permission cascades and rules are not filters.
A better structure is to keep the list of user profiles (currently just their name) separate from the list of friends for each user.
keep the friends as a set
You current have just a single value for the friends property. As you start building the app you will need to store multiple friends. The most common is to then store an array or list of UIDS:
[ UID1, UID2, UID3 ]
Or
{
"-K.......1": "UID1"
"-K.......5": "UID2"
"-K.......9": "UID3"
}
These are unfortunately the wrong type for this data structure. Both the array and the second collection are lists: an ordered collection of (potentially) non-unique values. But a collection of friends doesn't have to be ordered, it has to be unique. I'm either in the collection or I'm not in there, I can't be in there multiple times and the order typically doesn't matter. That's why you often end up looking for friends.contains("UID1") or ref.orderByValue().equalTo("UID1") operations with the above models.
A much better model is to store the data as a set. A set is a collection of unordered values, which have to be unique. Perfect for a collection of friends. To store that in Firebase, we use the UID as the key of the collection. And since we can't store a key without a value, we use true as the dummy value.
So this leads to this data model:
{
users:{
UID:{
nickname: hello
}
UID2:{
nickname: world
}
}
friends:{
UID:{
UID2: true
}
UID2:{
UID: true
}
}
}
There is a lot more to say/learn about NoSQL data modeling in general and Firebase specifically. To learn about that, I recommend reading NoSQL data modeling and watching Firebase for SQL developers.
I keep a collection of Friends where the users field is an array of 2 user ids: ['user1', 'user2'].
Getting the friends of a user is easy:
friendsCollection.where("users", "array-contains", "user1").get()
This should get you all documents where user1 appears.
Now the tricky part was on how to query a single friend. Ideally, firebase would support multiple values in array-contains, but they won't do that: https://github.com/firebase/firebase-js-sdk/issues/1169
So they way I get around this is to normalize the users list before adding the document. Basically I'm utilizing JS' truthiness to check what userId is greater, and which is smaller, and then making a list in that order.
when adding a friend:
const user1 = sentBy > sentTo ? sentBy : sentTo
const user2 = sentBy > sentTo ? sentTo : sentBy
const friends = { users: [user1, user2] }
await friendsCollection.add(friends)
This basically ensures that whoever is part of the friendship will always be listed in the same order, so when querying, you can just:
await friendsCollection.where("users", "==", [user1, user2]).get()
This obviously only works because I trust the list will always have 2 items, and trust that the JS truthiness will work deterministically, but it's a great solution for this specific problem.
I have auto-increment ids as primary is all of my db tables, like users, orders etc. I do not want to expose these ids to end users, as they may iterate over IDs can get access to user details. Instead I want to use a 2-way maths function such that I can obfuscate and de-obfuscate an id without storing a DB mapping.
function obfuscate(id)
{
constSeed = 1203793
return (id*constSeed)
}
function deobfuscate(bigid)
{
constSeed = 1203793
return (bigid/constSeed)
}
I can even run the bigid through a base36 converter, to get a smaller alphanumeric id, publicly exposable.
Are issues with this approach? Any other suggestions?
If you don't want them with access to the ID's maybe use them only in $_SESSION variables or something along those lines.
If the data is visible to the end user, even if you hash or encrypt the data,
it will not be safe.
I'm really beginner of nodejs. I want to make a chatting service using nodejs. I use nodejs/jade/mysql to construct basic part of my system and now I want to provide pub/sub to users.
We receive users' interests from text field or using hash tags (anyway we received users' interests and stored in MySQL -> we did it). Then, we want to show users chatting room list according to their interests. For instance A's interests are 'game', 'car' and 'food', then we search chat rooms with 'game', 'car', 'food' and show A these chat rooms first.
I want to use redis to provide this service but i really have no idea!
1) I installed redis and can run redis-server.
2)
//redis
var redis = require('redis');
var publisher = redis.createClient();
var subscriber = redis.createClient();
subscriber.on('message', function(channel, message){
console.log('Message ' + message + ' on channel ' + channel + ' arrived!');
});
subscriber.on('subscribe', function(channel){
publisher.publish('test', 'the a team');
publisher.publish('test', 'the b team');
})
subscriber.subscribe('test');
This is short code that I tried to understand redis.
3) I don't know how can I read data stored in Mysql and show users chat room according to their interests using redis.
Redis is a advanced key-value cache and store.Its operations cannot be directly mapped to mysql.
In redis you can set either key value pair or a hash under a key.
That is :
If you want to store your name in redis it can be done by:
var client = redis.createClient();
client.set("name", "John")
Retrieve the values using client.get("name")
Similarly under a single key you can store multiple key value pairs, as hash.
That under a name if you want to store their details like age, place, company etc.Then hash should be used.
Redis has method "hmset" and "hmget" for hash opertaions.
In redis like in cache you can set expiry time.
There are different method available. You can explore those.
For reference http://redis.io/commands
I am making a simple REST API in front of a NoSQL database that stores records as documents similar to JSON (but not exactly the same). Each record has some fields, including id for the database, and also including some derived fields, like dateCreated.
Any time I GET anything, I want to return the objects with all the fields.
// GET /users returns an array of these in JSON
// [{id:"xxx", name:"Bobby", dateCreated:"YYYY-MM-DD"]
data User = User { id :: String, name :: String, dateCreated :: XXX }
But any time I POST or PUT anything, they client should send an object with the id field and any derived fields missing. The database is responsible to create the id when I save it, and I would create some derived fields
// POST /users would need you to post only the name.
// {name:"Henry"}
data PartialUser = PartialUser { name :: String }
If resource represents objects of type User, what should I call the thing client is sending to me? Would you make all the derived fields Maybe values? Or would you create a second object called PostedUser or something?
It can be many things:
a request body
the representation of the intended resource state of the client
a command DTO which you can send to the domain logic in order to process it by CQRS
I would make it CreateUser command, but if you don't want to use CQRS and DDD, then you would probably call it as PartialUserRepresentation, or you don't create a data structure, just use the properties to create a new User entity. Ofc. if you use entities.
So I would say it depends on the architecture of your system.