web-dev-qa-db-fra.com

Comment stocker et récupérer un dictionnaire avec redis

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

Comment pourrais-je stocker my_dict et le récupérer avec redis. Par exemple, le code suivant ne fonctionne pas.

#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
44
PiccolMan

vous pouvez pickler votre dict et enregistrer en tant que chaîne.

import pickle
import redis

r = 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)
25
DaveQ

Une autre façon: vous pouvez utiliser la bibliothèque 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

Il convertit les types python en types Redis et inversement.

>>> 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'>

Disclaimer: J'ai écrit la bibliothèque. Voici le code: https://github.com/seperman/redisworks

13
Seperman

Comme la réponse de base a déjà été donnée par d'autres personnes, je voudrais en ajouter.

Voici les commandes dans REDIS pour effectuer des opérations de base avec les valeurs de type HashMap/Dictionary/Mapping.

  1. HGET => Renvoie la valeur d'une clé unique passée
  2. HSET => valeur définie/mise à jour pour la clé unique
  3. HMGET => Renvoie la valeur pour les clés simples/multiples passées 
  4. HMSET => set/updates les valeurs de la clé multiple
  5. HGETALL => Renvoie toutes les paires (clé, valeur) du mappage.

Voici leurs méthodes respectives dans la bibliothèque redis-py: -

  1. HGET => hget
  2. HSET => hset
  3. HMGET => hmget
  4. HMSET => hmset
  5. HGETALL => hgetall

Toutes les méthodes de définition ci-dessus créent le mappage, s'il n'existe pas . Toutes les méthodes de lecture ci-dessus ne génèrent pas d'erreur/d'exceptions, si le mappage/la clé dans le mappage n'existe pas.

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]: True

In [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]: True

In [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']

J'espère que cela rend les choses plus claires.

La commande redis SET stocke une chaîne, pas des données arbitraires. Vous pouvez essayer d’utiliser la commande redis HSET pour stocker le dict en tant que redis hash avec quelque chose comme:

for k,v in my_dict.iteritems():
    r.hset('my_dict', k, v)

mais les types de données redis et python ne s'alignent pas tout à fait. Les dict Python peuvent être imbriqués de manière arbitraire, mais un redis hash va exiger que votre valeur soit une chaîne. Une autre approche consiste à convertir vos données python en chaîne et à la stocker dans redis, quelque chose comme: 

r.set('this_dict', str(my_dict))

et lorsque vous récupérerez la chaîne, vous devrez l'analyser pour recréer l'objet python.

2
Jesusaur

Si vous souhaitez stocker un dict python dans redis, il est préférable de le stocker sous forme de chaîne json.

import redis

r = 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)

Lors de la récupération, déssérialisez-le à l'aide de json.loads

data = r.get('key1')
result = json.loads(data)
arr = result['var3']

Je préférerai SET/GET à HMSET/HGETALL car la complexité temporelle de cette dernière opération est O (N). 

Qu'en est-il des types (par exemple, octets) qui ne sont pas sérialisés par les fonctions json?

Vous pouvez écrire des fonctions de codeur/décodeur pour les types qui ne peuvent pas être sérialisés par les fonctions json. par exemple. écriture de la fonction encodeur/décodeur base64/ascii pour un tableau d'octets.

0
Saji Xavier

Essayez rejson-py qui est relativement nouveau depuis 2017. Regardez cette introduction .

from rejson import Client, Path

rj = 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)
0
Kevin Zhu