python - redis缓存json - 如何在redis中存储复杂对象(使用redis-py)




redis存储对象 (5)

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

python 3:

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

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的类型是一个字符串,而不是一个python对象,除了手动解析每个字段之外,还有什么方法可以解决这个问题吗?


实际上,您可以使用内置模块pickle在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

您可以按原样存储结构并执行'eval'以从String转换为Object:

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

您无法在Redis中创建嵌套结构,这意味着您不能(例如)将本机redis列表存储在本机redis哈希映射中。

如果你真的需要嵌套结构,你可能只想存储一个JSON-blob(或类似的东西)。 另一种选择是将“id”/键存储到不同的redis对象作为映射键的值,但是需要多次调用服务器才能获得完整的对象。


这是一个围绕Redis的简单包装器,用于pickle / 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存储它的二进制版本),你可以用repr和pickle.loads替换pickle.dump和ast.literal_eval。 对于json,请使用json.dumps和json.loads。

如果您始终使用简单字符串的键,则可以从键中删除酸洗。





redis