Nested Hash in Redis

Nested hash in redis

you can't use nested hash in redis,
but in the kind of situation you are asking you can use two hashes, one for key to subkey
and the other one for subkey to your values.

Is it possible to store nested dict in Redis as hash structure?

Redis alone doesn't store nested structures in hashes. There is a good answer for how to work around here.

However, there is a module RedisJSON that supports this and the python redis client includes support for this module.

Load the module in the redis server:

redis-server --loadmodule ../RedisJSON/target/release/librejson.dylib

In python you can then set and retrieve nested dicts or portions of the path.

import redis
from redis.commands.json.path import Path

redis_connection = StrictRedis(host='localhost', port=6379, charset="utf-8", decode_responses=True)

foo = {
"host_data": {
"hostname": "some_host",
"mac_address": "82:fa:8e:63:40:05",
"root_password": {
"is_crypted": True,
"password": "sha512_password"
},
"network": {
"ip_address": "192.168.0.10/24",
"default_gateway": "192.168.0.1",
"vmnic": "vmnic3",
"vlan": 20
},
"dns_servers": [
"dns01.local",
"dns02.local"
]
},
"installation_type": "esxi",
"image_data": {
"type": "vCenter_contentlib",
"host": "vcenter01",
"credential": {
"username": "some_user",
"password": "some_password"
},
"content_library": "the_content_lib_name",
"image_name": "some_image"
},
"host_short_name": "esxi021"
}

redis_connection.json().set("test", Path.rootPath(), foo)
print(redis_connection.json().get("test", '.host_data.hostname'))

Redis – Nested hashes vs. string values

You should consider storing the Access Control List (a list of permissions attached to a user-machine) as a redis hash.

This way you can query the entire collection of permissions for a subject or just query for a particular object permission.

For example, you have the following users (Subjects):

  • john:machine1
  • john:machine2
  • mary:machine1

The following features (or Objects):

  • editname
  • deletemachine

And the following Permissions:

  • Y (access granted)
  • N (access denied)

You can have one hash for each subject with key -> field -> value as follows:

ACL:{username}:{machine} -> {object} -> {permission}

So you can query for a particular object permission like this:

redis> HGET ACL:john:machine2 editname
"Y"

Or query the entire the collection of permissions for a subject:

redis> HGETALL ACL:john:machine2
1) "editname"
2) "Y"
3) "deletemachine"
4) "N"

Of course you can choose to store only the granted permissions, and assume a denied permission by default.

Save nested hash in redis via a node.js app

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.

Complex data structures Redis

What would the 'usual' way to store such a data structure (or would
you not?)

For example harry and sally would be stored each in separate hashes where fields would represent their properties like age and weight. Then set structure would hold all the members (harry, sally, ...) which you have stored in redis.

Would you be able to directly get a value (e.g. get harry : age ?)

Yes, see HGET or HMGET or HGETALL.

Once stored could you directly change the value of a sub key (e.g.
sally : weight = 100)

Yes, see HSET.

How can I store nested Hashmap in Redis?

Redis doesn't support it as of now. However there is a way to do it, other than rejson.

You can convert it into JSON and store in Redis and retrieve. Following utility methods, which I use in Jackson.

To convert Object to String :

public static String stringify(Object object) {
ObjectMapper jackson = new ObjectMapper();
jackson.setSerializationInclusion(JsonSerialize.Inclusion.NON_NULL);
try {
return jackson.writeValueAsString(object);
} catch (Exception ex) {
LOG.log(Level.SEVERE, "Error while creating json: ", ex);
}
return null;
}

Example : stringify(obj);

To convert String to Object :

public static <T> T objectify(String content, TypeReference valueType) {
try {
ObjectMapper mapper = new ObjectMapper();
mapper.configure(Feature.WRITE_DATES_AS_TIMESTAMPS, false);
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss.SSS");
dateFormat.setTimeZone(Calendar.getInstance().getTimeZone());
mapper.setDateFormat(dateFormat);
return mapper.readValue(content, valueType);
} catch (Exception e) {
LOG.log(Level.WARNING, "returning null because of error : {0}", e.getMessage());
return null;
}
}

Example : List<Object> list = objectify("Your Json", new TypeReference<List<Object>>(){})

You can update this method as per your requirement. I am sure, you know, how to add and update in Redis.



Related Topics



Leave a reply



Submit