如何存储在redis的复杂对象(使用redis的-PY)(how to store a comple

2019-07-21 00:11发布

该hmset功能可以设置每个字段的值,但我发现,如果值本身是一个复杂的结构化对象,从hget的价值回归是一个序列化的字符串,而不是原来的对象

images= [{'type':'big', 'url':'....'},
     {'type':'big', 'url':'....'},
     {'type':'big', 'url':'....'}]   

redis = Redis()
redis.hset('photo:1', 'images', images)

i = redis.hget('photo:1', 'images')
print type(i)

i的类型是一个字符串,而不是一个对象蟒,是否有任何方式来手动除了解决这个问题解析每个字段?

Answer 1:

你不能在Redis的创建嵌套结构,这意味着你不能(例如)存储本地Redis的哈希地图中的本地Redis的列表。

如果你真的需要嵌套结构,您可能希望只存储一个JSON二进制大对象(或类似的东西)来代替。 另一种选择是存储的“ID” /关键,不同的Redis对象为地图键的值,但需要到服务器多次调用得到充分的对象。



Answer 2:

其实,你可以存储在使用内置模块redis的Python对象咸菜 。

下面是例子。

import pickle
import redis

r = redis.StrictRedis(host='localhost', port=6379, db=0)
obj = ExampleObject()
pickled_object = pickle.dumps(obj)
r.set('some_key', pickled_object)
unpacked_object = pickle.loads(r.get('some_key'))
obj == unpacked_object


Answer 3:

JSON实施例:

import json
import redis

r = redis.StrictRedis(host='localhost', port=6379, db=0)

images= [
    {'type':'big', 'url':'....'},
    {'type':'big', 'url':'....'},
    {'type':'big', 'url':'....'},
]

json_images = json.dumps(images)
r.set('images', json_images)
unpacked_images = json.loads(r.get('images'))
images == unpacked_images

蟒蛇3:

unpacked_images = json.loads(r.get('images').decode('utf-8'))
images == unpacked_images


Answer 4:

我创建了一个库, SubRedis ,它可以让你创建Redis的更复杂的结构/层次。 如果你给它一个Redis的实例和一个前缀,它给你一个几乎完全有能力和独立的Redis实例。

redis = Redis()
photoRedis = SubRedis("photo:%s" % photoId, redis)
photoRedis.hmset('image0', images[0])
photoRedis.hmset('image1', images[1])
...

SubRedis刚刚结束了前面附加传给它作为前缀到平坦redis的数据结构的字符串。 我觉得这是我结束了Redis的做了很多的模式一个方便的包装 - 前面加上一些ID巢一些数据。



Answer 5:

您可以使用RedisWorks库。

pip install redisworks

>>> from redisworks import Root
>>> root = Root()
>>> root.something = {1:"a", "b": {2: 2}}  # saves it as Hash
>>> print(root.something)  # loads it from Redis
{'b': {2: 2}, 1: 'a'}
>>> root.something['b'][2]
2

它把蟒蛇类型Redis的类型,反之亦然。

>>> root.sides = [10, [1, 2]]  # saves it as list in Redis.
>>> print(root.sides)  # loads it from Redis
[10, [1, 2]]
>>> type(root.sides[1])
<class 'list'>

免责声明:我写的库。 下面是代码: https://github.com/seperman/redisworks



Answer 6:

下面是围绕Redis的哪个泡菜/ unpickles数据结构一个简单的包装:

from redis import Redis
from collections import MutableMapping
from pickle import loads, dumps


class RedisStore(MutableMapping):

    def __init__(self, engine):
        self._store = Redis.from_url(engine)

    def __getitem__(self, key):
        return loads(self._store[dumps(key)])

    def __setitem__(self, key, value):
        self._store[dumps(key)] = dumps(value)

    def __delitem__(self, key):
        del self._store[dumps(key)]

    def __iter__(self):
        return iter(self.keys())

    def __len__(self):
        return len(self._store.keys())

    def keys(self):
        return [loads(x) for x in self._store.keys()]

    def clear(self):
        self._store.flushdb()


d = RedisStore('redis://localhost:6379/0')
d['a'] = {'b': 1, 'c': 10}
print repr(d.items())
# this will not work: (it updates a temporary copy and not the real data)
d['a']['b'] = 2
print repr(d.items())
# this is how to update sub-structures:
t = d['a']
t['b'] = 2
d['a'] = t
print repr(d.items())
del d['a']

# Here is another way to implement dict-of-dict eg d['a']['b']
d[('a', 'b')] = 1
d[('a', 'b')] = 2
print repr(d.items())
# Hopefully you do not need the equivalent of d['a']
print repr([{x[0][1]: x[1]} for x in d.items() if x[0][0] == 'a'])
del d[('a', 'b')]
del d[('a', 'c')]

如果你喜欢在Redis的(泡菜店它的二进制版本)明文可读的数据,你可以替换再版和pickle.loads与ast.literal_eval pickle.dumps。 对于JSON,使用json.dumps和json.loads。

如果你总是使用的是一个简单的字符串键,可以删除密钥的酸洗。



Answer 7:

你可以存储你的结构是,做一个“EVAL”从字符串转换为对象:

images= [{'type':'big', 'url':'....'},
 {'type':'big', 'url':'....'},
 {'type':'big', 'url':'....'}]   
redis = Redis()
redis.hset('photo:1', 'images', images)

i = eval(redis.hget('photo:1', 'images'))
print type(i) #type of i should be list instead of string now


文章来源: how to store a complex object in redis (using redis-py)
标签: python redis