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)
Run Code Online (Sandbox Code Playgroud)
i的类型是一个字符串,而不是一个python对象,除了手动解析每个字段之外,还有什么方法可以解决这个问题吗?
Kyr*_*kov 81
实际上,您可以使用内置模块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
Run Code Online (Sandbox Code Playgroud)
Jon*_*org 48
您无法在Redis中创建嵌套结构,这意味着您不能(例如)将本机redis列表存储在本机redis哈希映射中.
如果你真的需要嵌套结构,你可能只想存储一个JSON-blob(或类似的东西).另一种选择是将"id"/键存储到不同的redis对象作为映射键的值,但是需要多次调用服务器才能获得完整的对象.
Civ*_*Fan 44
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
Run Code Online (Sandbox Code Playgroud)
python 3:
unpacked_images = json.loads(r.get('images').decode('utf-8'))
images == unpacked_images
Run Code Online (Sandbox Code Playgroud)
小智 7
您可以将RedisLabs 中的RedisJSON与python 客户端一起使用。它支持嵌套数据结构。对于这样的任务非常有用。
示例中的一些代码:
# Set the key `obj` to some object
obj = {
'answer': 42,
'arr': [None, True, 3.14],
'truth': {
'coord': 'out there'
}
}
rj.jsonset('obj', Path.rootPath(), obj)
# Get something
print 'Is there anybody... {}?'.format(
rj.jsonget('obj', Path('.truth.coord'))
)
Run Code Online (Sandbox Code Playgroud)
我创建了一个库SubRedis,它使您可以在Redis中创建更复杂的结构/层次结构。如果为它提供一个redis实例和一个前缀,它将为您提供几乎完全有能力且独立的redis实例。
redis = Redis()
photoRedis = SubRedis("photo:%s" % photoId, redis)
photoRedis.hmset('image0', images[0])
photoRedis.hmset('image1', images[1])
...
Run Code Online (Sandbox Code Playgroud)
SubRedis最终只是将传入的字符串作为前缀添加到平面redis数据结构上。我发现这对于我最终在redis中做很多工作的模式来说是一个方便的包装器-预先添加一些ID以嵌套一些数据。
您可以使用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
Run Code Online (Sandbox Code Playgroud)
它将 python 类型转换为 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'>
Run Code Online (Sandbox Code Playgroud)
免责声明:我写了这个库。这是代码: https: //github.com/seperman/redisworks
这是一个围绕 Redis 的简单包装器,它腌制/取消腌制数据结构:
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')]
Run Code Online (Sandbox Code Playgroud)
如果您更喜欢 redis 中的纯文本可读数据(pickle 存储它的二进制版本),您可以将 pickle.dumps 替换为 repr,将 pickle.loads 替换为 ast.literal_eval。对于 json,使用 json.dumps 和 json.loads。
如果您总是使用简单字符串的键,则可以从键中删除酸洗。
归档时间: |
|
查看次数: |
67183 次 |
最近记录: |