Jak przechowywać i pobierać słownik za pomocą redis


# I have the dictionary my_dict
my_dict = {
'var1' : 5
'var2' : 9
}
r = redis.StrictRedis()

Jak będę przechowywać my_dict i odzyskać go za pomocą redis. Na przykład poniższy kod nie działa.
#Code that doesn't work
r.set('this_dict', my_dict) # to store my_dict in this_dict
r.get('this_dict') # to retrieve my_dict

Zaproszony:
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Możesz to zrobić za pomocą
hmset
(wiele kluczy można ustawić za pomocą
hmset
).
hmset("RedisKey", dictionaryToSet)
import redis
conn = redis.Redis('localhost')user = {"Name":"Pradeep", "Company":"SCTL", "Address":"Mumbai", "Location":"RCP"}conn.hmset("pythonDict", user)conn.hgetall("pythonDict"){'Company': 'SCTL', 'Address': 'Mumbai', 'Location': 'RCP', 'Name': 'Pradeep'}
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

możesz marynować swój dykt i zapisać jako ciąg.
import pickle
import redisr = redis.StrictRedis('localhost')
mydict = {1:2,2:3,3:4}
p_mydict = pickle.dumps(mydict)
r.set('mydict',p_mydict)read_dict = r.get('mydict')
yourdict = pickle.loads(read_dict)
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Inny sposób: możesz skorzystać z biblioteki
RedisWorks
.
pip install redisworks
>>> from redisworks import Root
>>> root = Root()
>>> root.something = {1:"a", "b": {2: 2}} # saves it as Hash type in Redis...
>>> print(root.something) # loads it from Redis
{'b': {2: 2}, 1: 'a'}
>>> root.something['b'][2]
2

Konwertuje typ Pythona na typ Redis i na odwrót.
>>> 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'>

Zastrzeżenie: napisałem bibliotekę. Oto kod:

https://github.com/seperman/redisworks
https://github.com/seperman/redisworks
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Jeśli chcesz przechowywać dict Pythona w redis, lepiej zapisać go jako ciąg json.
import redisr = redis.StrictRedis(host='localhost', port=6379, db=0)
mydict = { 'var1' : 5, 'var2' : 9, 'var3': [1, 5, 9] }
rval = json.dumps(mydict)
r.set('key1', rval)

Podczas pobierania usuń serializację za pomocą json.loads
data = r.get('key1')
result = json.loads(data)
arr = result['var3']

Wolę SET/GET zamiast HMSET/HGETALL, ponieważ złożoność czasowa ostatniej operacji wynosi O (N).

A co z typami (np. Bajty), które nie są serializowane przez funkcje json?

Można pisać funkcje kodera/dekodera dla typów, których nie można serializować za pomocą funkcji JSON. np. napisz funkcję kodera/dekodera base64/ascii dla tablicy bajtów.
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Ponieważ podstawowej odpowiedzi udzieliły już inne osoby, chciałbym dodać kilka z nich.
Poniżej znajdują się polecenia w
REDIS
służące do wykonywania podstawowych operacji na wartościach, takich jak
HashMap/Dictionary/Mapping
.
  • HGET = & > zwraca wartość dla jednego przekazanego klucza
  • HSET = & > ustaw/zaktualizuj wartość dla jednego klucza
  • HMGET = & > zwraca wartość dla co najmniej jednego przekazanego klucza
  • HMSET = & > ustawianie/aktualizowanie wartości dla wielu kluczy
  • HGETALL = & > zwraca wszystkie pary (klucz, wartość) na mapie.

Oto ich metody w bibliotece
redis-py
: -
  • HGET => hget
  • HSET => hset
  • HMGET => hmget
  • HMSET => hmset
  • HGETALL => hgetall

Wszystkie powyższe metody ustawiające tworzą mapowanie, jeśli nie istnieje.
Wszystkie powyższe metody pobierające nie zgłaszają błędów/wyjątków, jeśli mapowanie/klucz w mapowaniu nie istnieje.
Example:
=======
In [98]: import redis
In [99]: conn = redis.Redis('localhost')In [100]: user = {"Name":"Pradeep", "Company":"SCTL", "Address":"Mumbai", "Location":"RCP"}In [101]: con.hmset("pythonDict", {"Location": "Ahmedabad"})
Out[101]: TrueIn [102]: con.hgetall("pythonDict")
Out[102]:
{b'Address': b'Mumbai',
b'Company': b'SCTL',
b'Last Name': b'Rajpurohit',
b'Location': b'Ahmedabad',
b'Name': b'Mangu Singh'}In [103]: con.hmset("pythonDict", {"Location": "Ahmedabad", "Company": ["A/C Pri
...: sm", "ECW", "Musikaar"]})
Out[103]: TrueIn [104]: con.hgetall("pythonDict")
Out[104]:
{b'Address': b'Mumbai',
b'Company': b"['A/C Prism', 'ECW', 'Musikaar']",
b'Last Name': b'Rajpurohit',
b'Location': b'Ahmedabad',
b'Name': b'Mangu Singh'}In [105]: con.hget("pythonDict", "Name")
Out[105]: b'Mangu Singh'In [106]: con.hmget("pythonDict", "Name", "Location")
Out[106]: [b'Mangu Singh', b'Ahmedabad']

Mam nadzieję, że to wszystko wyjaśnia.
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Możesz podejść do tego pytania inaczej:
import redis
conn = redis.Redis('localhost')v={'class':'user','grants': 0, 'nome': 'Roberto', 'cognome': 'Brunialti'}y=str(v)
print(y['nome']) #<=== this return an error as y is actually a string
conn.set('test',y)z=eval(conn.get('test'))
print(z['nome']) #<=== this really works!

Nie testowałem tego pod kątem wydajności/szybkości.
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Polecenie redis SET przechowuje ciąg, a nie dowolne dane. Możesz spróbować użyć polecenia redis HSET, aby zapisać dict jako skrót redis z czymś w rodzaju
for k,v in my_dict.iteritems():
r.hset('my_dict', k, v)

ale typy danych redis i python nie są dokładnie takie same. Python dyktuje mogą być dowolnie zagnieżdżone, ale redis będzie wymagał, aby twoja wartość była ciągiem. Innym podejściem, którego możesz użyć, jest przekonwertowanie danych Pythona na łańcuch i przechowywanie ich w redis, na przykład
r.set('this_dict', str(my_dict))

a kiedy otrzymasz ciąg, będziesz musiał go przeanalizować, aby odtworzyć obiekt Pythona.
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Można rozważyć użycie MessagePack

,
https://msgpack.org/index.html
który jest zatwierdzony przez redis.
import msgpackdata = {
'one': 'one',
'two': 2,
'three': [1, 2, 3]
}await redis.set('my-key', msgpack.packb(data))
val = await redis.get('my-key')
print(msgpack.unpackb(val))# {'one': 'one', 'two': 2, 'three': [1, 2, 3]}

Za pomocą

msgpack-python
https://github.com/msgpack/msgpack-python
i

aioredis
https://github.com/aio-libs/aioredis
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

HMSET jest przestarzały. Teraz możesz używać HSET z takim słownikiem:
import redis
r = redis.Redis('localhost')key = "hashexample"
queue_entry = {
"version":"1.2.3",
"tag":"main",
"status":"CREATED",
"timeout":"30"
}
r.hset(key,None,None,queue_entry)
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Próbować

rejson-py
https://github.com/RedisLabs/rejson-py
który jest stosunkowo nowy od 2017 roku. Spójrz na to

wprowadzenie
https://redislabs.com/blog/redis-as-a-json-store/
.
from rejson import Client, Pathrj = Client(host='localhost', port=6379)# 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')))# Delete something (or perhaps nothing), append something and pop it
rj.jsondel('obj', Path('.arr[0]'))
rj.jsonarrappend('obj', Path('.arr'), 'something')
print '{} popped!'.format(rj.jsonarrpop('obj', Path('.arr')))# Update something else
rj.jsonset('obj', Path('.answer'), 2.17)
Anonimowy użytkownik

Anonimowy użytkownik

Potwierdzenie od:

Jeśli nie masz pewności, jak uporządkować dane w Redis, przeprowadziłem kilka testów porównawczych, w tym analizę wyników.
W słowniku, którego użyłem (

re
) to klucze 437.084 (format MD5) i wartości w tym formularzu:
{"path": "G:\tests\2687.3575.json",
"info": {"f": "foo", "b": "bar"},
"score": 2.5}


Pierwszy test

(wstaw dane do mapowania klucz-wartość redis):
conn.hmset('my_dict', d) # 437.084 keys added in 8.98sconn.info()['used_memory_human'] # 166.94 Mbfor key in d:
json.loads(conn.hget('my_dict', key).decode('utf-8').replace("'", '"'))
# 41.1 simport ast
for key in d:
ast.literal_eval(conn.hget('my_dict', key).decode('utf-8'))
# 1min 3sconn.delete('my_dict') # 526 ms


Drugi test

(wstawianie danych bezpośrednio do kluczy Redis):
for key in d:
conn.hmset(key, d[key]) # 437.084 keys added in 1min 20sconn.info()['used_memory_human'] # 326.22 Mbfor key in d:
json.loads(conn.hgetall(key)[b'info'].decode('utf-8').replace("'", '"'))
# 1min 11sfor key in d:
conn.delete(key)
# 37.3s

Jak widać, w drugim teście trzeba przeanalizować tylko wartości „info”, ponieważ hgetall (klucz) już zwraca dict, ale nie zagnieżdżony.
I oczywiście najlepszym przykładem użycia Redisa jako dyktanda w Pythonie jest

pierwszy test

Aby odpowiedzieć na pytania, Zaloguj się lub Zarejestruj się