Storing multiple nested objects in redis Storing multiple nested objects in redis json json

Storing multiple nested objects in redis


You can use the ReJSON Redis Module and store the objects directly. http://rejson.io/


Option 1

I think if you are searching for an implementation language independent way, i.e. the same operation and result are expected in different parts of the system written in different programming languages, then @Not_a_Golfer 's recommendation is best suited for your case.

Option 2

However, if you happened to be using Java only and you are not running Redis 4.0 yet, I would recommend you use Redisson as your client side library to make this job a lot easier for yourself.

Disclaimer, I am a member of the Redisson project, my view below is biased. It is also written in a hope that it can reach to others who are in this exact situation.

Redisson is a client side Java library that lets you operate Redis as an In-Memory Data Grid. Multi-dimensional complex objects are naturally supported.

Redisson provides Redis data types with standard Java interfaces, i.e. Redis hash is provided as java.util.Map and java.util.concurrent.ConcurrentMap so in your case the usage would be simply be:

//lets imagine you have a builder that creates users User user01 = new User();user01.setUsername("ally");user01.setEmail("all@gmail.com");User user02 = new User();user02.setUsername("user2");user02.setEmail("...");//You get a Redis hash handler that works as a standard Java mapMap<String, User> users = redisson.getMap("users");//This is how you put your data in Redis//Redisson serialize the data into JSON format by defaultusers.put("user01", user01);users.put("user02", user02);//the same works for trucksTruck truck01 = new Truck();truck01.setRegNo("azn102");truck01.setMake("subaru");Truck truck02 = new Truck();truck02.setRegNo("kcaher3");truck02.setMake("...");//The same as aboveMap<String, Truck> trucks = redisson.getMap("trucks");trucks.put("truck01", truck01);trucks.put("truck02", truck02);

Getting your data out is just as easy

User user01 = users.get("user01");Truck truck02 = trucks.get("truck02");

In Redis, what you would get is two hashes, one called users and another called trucks, you would see JSON strings are stored against specified field names in these hash objects.

Now, you may argue this is not really a nested objects, this is just a data serialization.

OK, lets make the example a little more complex to see the difference: What if you want to keep a list of all the users who had driven a particular truck, you may also want to easily find out which truck a user is currently driving.

I would say these are fairly typical business use cases.

That really adds more dimensions and complexity to the data structures. Normally you would have to break them in to different pieces:

  • You would need the Truck and User be mapped to a different hash to avoid data duplication and consistency issue;

  • You would also need to manage a separate list for each truck to store the usage log.

In Redisson, these type of tasks are handled more naturally and without bearing the aforementioned worries in mind.

You would simply do, as you would normally, in Java like this:

  • Annotate your User class and Truck class with @REntity annotation, and choose an identifier generator or specifier your own, this could be the value of a field.

  • Add a List field (usageLog) to Truck class.

  • Add a Truck field (currentlyDriving) to User class.

That's all you need. So the usage is not much more than you would normally do in Java:

//prepare the service and register your class.RLiveObjectService service = redisson.getLiveObjectService();service.registerClass(User.class);service.registerClass(Truck.class);Truck truck01 = new Truck();truck01.setRegNo("azn102");truck01.setMake("subaru");//stores this record as a Redis hashservice.persist(truck01);User user02 = new User();user02.setUsername("user2");user02.setEmail("...");//stores this record as a Redis hashservice.persist(user02);//assuming you have invoked setUsageLog elsewhere.truck01.getUsageLog().add(user02);user02.setCurrentlyDriving(truck01);//under normal circumstance keeping a Redis hash registry is not necessary.//the service object can be used for this type of look up.//this is only for demonstration.Map<String, Truck> trucks = redisson.getMap("trucks");trucks.put("truck01", truck01);Map<String, User> users = redisson.getMap("users");users.put("user02", user02);

So what you get in the end is each record is stored in Redis and a hash, and each truck record keeps an independent list of user records who has used it, user record now has information of the truck he/she is currently driving. All of these things are done using object references instead of duplicating the domain records.

As you can see Redisson provides a solution that ticks all the boxes and takes the headaches away during the process.

For more information relating to how Redisson handles multi-dimensional complex objects in Redis through object hash mapping and object referencing:


I think better you can use HMSET to save keys.

Like in your case you can create a HMSET with name "users" & "trucks". In that HMSET you can create keys (i.e. fields) like "user01" and "user02". As these keys(like "user01", "user02" etc) are able to store value in it, so you can store your rest (i.e. {username:"ally", email:"all@gmail.com"}) of JSON object in stringified form.

For example: HMSET users user01 "{\"username\":\"ally\",\"email\":\"all@gmail.com\"}"

After this you can get your users list by HGETALL (like by using HGETALL users).Similarly, if you need to fetch user details of "user01" then you can use HGET like HGET users user01. After fetching value of "user01" you can parse that value and use according to your requirement.