29

I'm using node_redis and I'd like to save a structure like:

{
users : 
    "alex" : { "email" : "alex@gmail.com",
           "password" : "alex123"},
    "sandra" : { "email" : "sandra@gmail.com",
           "password" : "sandra123"},
    ...
}

Currently, for each user I create a JSON object:

jsonObj = { "email" : "alex@gmail.com",
            "password" : "alex123"}

and do a

db.hmset("alex", JSON.stringify(jsonObj))

Is it possible to embedded this strucute in another structure (the users one ?) How could I set users["alex"] with this structure ?

Luc
  • 16,604
  • 34
  • 121
  • 183
  • Don't you mean `db.hmset("users", "alex", JSON.stringify(jsonObj))` instead of `db.hmset("alex", JSON.stringify(jsonObj))`??? – BMiner Sep 24 '13 at 19:19
  • Check [this answer](https://stackoverflow.com/questions/16094574/alternatives-to-nested-structures-in-redis/57856223#57856223) for alternative on how to save nested data structures to Redis. – for_stack Sep 09 '19 at 15:23

2 Answers2

25

As far as I know there isn't native support for nested structures in Redis, but they can be modeled for example with set+hash (similar to hierarchical trees). Hashes are probably best suited for storing fields and values of single JSON object. What I would do is to store each user with a prefix (which is a Redis convention), for example:

db.hmset("user:alex", JSON.stringify(jsonObj));

and then use sets to group users into one set with a key named users. I can then get all of the users keys by smembers command and access each of them individually with hgetall.

John Zwinck
  • 239,568
  • 38
  • 324
  • 436
yojimbo87
  • 65,684
  • 25
  • 123
  • 131
  • thanks, this is a good approach. Then, when you need to update a particuliar user, do you "srem "users" "user:alex" and create a new set to add to users ? – Luc Apr 18 '11 at 15:00
  • @Luc: If the update doesn't affect his name which is used as a part of the key "user:alex" then you don't have to remove or add him again to the set. You just change specified fields in that hash and that should be all. In case when you are changing also his name you would probably have to delete the original "user:alex" hash and create new one. Then you would remove "user:alex" from "users" set and add there newly created hash key. – yojimbo87 Apr 18 '11 at 15:11
  • I now use this approach (mix of Hash and Set). But the update does not work by only modifying the user object retrieved. It seems we have to "hmset user:alex user" once again. – Luc Apr 18 '11 at 22:21
  • 4
    I'm not sure that I understand this answer at all. You say that hashes are probably best suited for storing fields and values of a single JSON Object. Why is that better than simply just storing the JSON-encoded value to a string using SET? Are you comparing `HSET user:{id} name Fred` vs. `SET user:{id} '{"name":"Fred"}'`? If so, I'd presume that SET (and subsequent JSON parsing) is more often faster than HSET if you are frequently accessing all of the fields of the Object. Thoughts? – BMiner Sep 24 '13 at 19:24
  • SET with JSON parsing being faster is questionable since it would probably highly depend on the string length which will be parsed and subsequently saved whereas HSET will process only required small part of the entire JSON object. If all fields are accessed SET could be a viable option and benchmarks with comparison could be interesting to see. – yojimbo87 Sep 24 '13 at 20:34
16

You could store the sub structure as an object and store it's id within the main structure, rather like a pointer. So, given your example, I would do the following

{
users : 
    "alex" : { "email" : "alex@gmail.com",
           "password" : "alex123"},
    "sandra" : { "email" : "sandra@gmail.com",
           "password" : "sandra123"},
    ...
}
$x = incr idx:user
hmset user:$x email alex@gmail.com password alex123
sadd list:user $x

$x = incr idx:user
hmset user:$x email sandra@gmail.com password sandra123
sadd list:user $x

Hope this possible solution helps

yojimbo87
  • 65,684
  • 25
  • 123
  • 131
Lloyd Moore
  • 3,117
  • 1
  • 32
  • 32