【问题标题】:Is it possible to store nested dict in Redis as hash structure?是否可以将 Redis 中的嵌套字典存储为哈希结构?
【发布时间】:2022-01-09 04:47:51
【问题描述】:

我正在尝试使用 HSET 将嵌套字典存储为哈希,但这似乎是不可能的。

不起作用的示例:

from redis import StrictRedis
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 = StrictRedis(host='localhost', port=6379, charset="utf-8", decode_responses=True)
redis_connection.hset("test", mapping=foo)

抛出以下错误:

Traceback (most recent call last):
  File "/Users/project/dummy.py", line 36, in <module>
    redis_connection.hset("test", mapping=thing)
  File "/Users/project/venv/lib/python3.9/site-packages/redis/client.py", line 3050, in hset
    return self.execute_command('HSET', name, *items)
  File "/Users/project/venv/lib/python3.9/site-packages/redis/client.py", line 900, in execute_command
    conn.send_command(*args)
  File "/Users/project/venv/lib/python3.9/site-packages/redis/connection.py", line 725, in send_command
    self.send_packed_command(self.pack_command(*args),
  File "/Users/project/venv/lib/python3.9/site-packages/redis/connection.py", line 775, in pack_command
    for arg in imap(self.encoder.encode, args):
  File "/Users/project/venv/lib/python3.9/site-packages/redis/connection.py", line 119, in encode
    raise DataError("Invalid input of type: '%s'. Convert to a "
redis.exceptions.DataError: Invalid input of type: 'dict'. Convert to a bytes, string, int or float first.

有效的示例:

from redis import StrictRedis
foo = {
    "installation_type": "esxi",
    "host_short_name": "esxi021"
}

redis_connection = StrictRedis(host='localhost', port=6379, charset="utf-8", decode_responses=True)
redis_connection.hset("test", mapping=foo)

总之,我的问题是:

是否可以将嵌套的 dict 存储为 Redis 中的哈希结构?

注意:我知道它可以存储为字符串,然后加载为 json,但我真的想避免它。

编辑: Reids 版本是 6.2.5

【问题讨论】:

标签: python redis redis-py


【解决方案1】:

Redis 本身不会将嵌套结构存储在哈希中。对于如何解决here,有一个很好的答案。

但是,有一个模块 RedisJSON 支持此功能,python redis client 包含对此模块的支持。

在redis服务器中加载模块:

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

然后,您可以在 python 中设置和检索嵌套的字典或部分路径。

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 库本身的一部分。我会看看周围的
  • 啊,对不起,我第一次传球时没听懂。我更新了答案并包含了一个示例。
  • 它仍然被存储为字符串,但至少你不必手动管理它。您能否在您的答案print(redis_connection.json().get("test", '.host_data.hostname')) 中添加类似的内容,以便插入和检索数据都可以填满?
  • 已更新。我对redisJSON模块的理解是:文档以二进制数据形式存储在树形结构中,可以快速访问子元素
  • 您的理解是正确的,但对某些人了解如何存储和检索数据可能会有所帮助,这就是我的观点
【解决方案2】:

别问这个问题,显然Redis只能使用扁平结构根据:https://redis.com/redis-best-practices/data-storage-patterns/object-hash-storage/

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-06-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多