hmset函数可以设置每个字段的值,但我发现如果值本身是一个复杂的结构化对象,则从hget返回的值是序列化字符串,而不是原始对象
e.g
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对象,除了手动解析每个字段之外,还有什么方法可以解决这个问题吗?
答案 0 :(得分:74)
实际上,您可以使用内置模块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
答案 1 :(得分:44)
您无法在Redis中创建嵌套结构,这意味着您无法(例如)将本机redis列表存储在本机redis哈希映射中。
如果你真的需要嵌套结构,你可能只想存储一个JSON-blob(或类似的东西)。另一种选择是将“id”/键存储到不同的redis对象作为映射键的值,但这需要多次调用服务器才能获得完整的对象。
答案 2 :(得分:5)
我创建了一个库SubRedis,它允许您在redis中创建更复杂的结构/层次结构。如果你给它一个redis实例和一个前缀,它会给你一个几乎完全能力和独立的redis实例。
redis = Redis()
photoRedis = SubRedis("photo:%s" % photoId, redis)
photoRedis.hmset('image0', images[0])
photoRedis.hmset('image1', images[1])
...
SubRedis最终将传入其中的字符串作为前缀添加到flat redis数据结构中。我发现这是一个方便的模式包装器,我最终在redis中做了很多 - 在一些id之前加上一些数据。
答案 3 :(得分:3)
您可以使用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
它将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'>
免责声明:我写了这个库。以下是代码:https://github.com/seperman/redisworks
答案 4 :(得分:3)
这是一个围绕Redis的简单包装器,用于pickle / unpickles数据结构:
file = open("text.txt","a")
n=0
while n<=5:
y = str(input("name: "))
x = int(input("marks: "))
result = "Pass"
if x<35:
result = "Fail"
print(y,result)
file.write('"{}#{}"/n', format(y,result))
elif 35<=x<=54:
result = "S"
print(y,result)
file.write('"{}#{}"/n', format(y,result))
elif 55<=x<=64:
result = "C"
print(y,result)
file.write('"{}#{}"/n', format(y,result))
elif 65<=x<=74:
result = "B"
print(y,result)
file.write('"{}#{}"/n', format(y,result))
elif (75<=x<=100):
result = "A"
print(y,result)
file.write('"{}#{}"/n', format(y,result))
else:
print ("Invalid Enter")
n = n+1
file.close
如果你更喜欢redis中的纯文本可读数据(pickle存储它的二进制版本),你可以用repr和pickle.loads替换pickle.dump和ast.literal_eval。对于json,请使用json.dumps和json.loads。
如果您始终使用简单字符串的键,则可以从键中删除酸洗。
答案 5 :(得分:2)
您可以将RedisLabs中的RedisJSON与client for 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'))
)
答案 6 :(得分:0)
我最近也遇到过类似的用例。在redis哈希中存储复杂的数据结构。
我认为解决此问题的最佳方法是将json对象序列化为字符串并将其存储为另一个对象的值。
打字稿示例
要存储在哈希图中的对象
const payload = {
"k1":"v1",
"k2": "v2",
"k3": {
"k4":"v4",
"k5":"v5"
}
}
将此有效负载存储为
await redis.hmset('hashMapKey', {somePayloadKey: JSON.stringify(payload) });
可以将其检索为
const result = await redis.hgetall('hashMapKey');
const payload = JSON.parse(result.somePayloadKey);
hmset和hgetall与redis中的HMSET和HGETALL等效,tedis。
希望这会有所帮助。
答案 7 :(得分:-1)
您可以按原样存储结构,并执行'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