रेडिस के साथ एक शब्दकोश कैसे स्टोर और पुनर्प्राप्त करें


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

मैं my_dict को कैसे स्टोर करूंगा और इसे redis के साथ पुनः प्राप्त करूंगा। उदाहरण के लिए, निम्न कोड काम नहीं करता है।

#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

जवाबों:


160

आप इसे कर सकते हैं hmset(एकाधिक कुंजियों का उपयोग करके सेट किया जा सकता है 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'}

48
अगर यह डेटा संरचना के बजाय केवल तानाशाही है, उदाहरण के लिए, कुछ सरणियों आदि को शामिल करते हुए, अपने डेटा json.dumps()को स्ट्रिंग के रूप में लिखने के साथ क्रमबद्ध करें और बाद में json.loads()इसे डेटा संरचना में वापस लाने के लिए रेडिस उपयोगकर्ता से पुनर्प्राप्त करें
andilabs

7
json.dumps()और json.loads()केवल तभी काम करेगा जब आप अपने शब्दकोश कीज़ के साथ हमेशा स्ट्रिंग्स रहेंगे। यदि आप नहीं हैं तो आप अचार का उपयोग करने पर विचार कर सकते हैं।
राईचूस

6
json बाइट्स के साथ संगत नहीं है इसलिए json सीरीज़ेशन एक वैश्विक समाधान नहीं है, उदाहरण के लिए, यदि आपके पास बाइट्स मान के साथ एक तानाशाही है तो यह काम नहीं करेगा।
टॉमी

8
ध्यान दें, के लिए प्रलेखन hmsetआपको यह नहीं बताता है, लेकिन यदि आप खाली डिक्टेट स्टोर करने की कोशिश करते हैं, तो यह एक DataError उठाता है।
१५'१

1
@ प्रदीप हम कैसे कुंजी को गतिशील बना सकते हैं। मान लीजिए कि डेटा हर 15 मिनट में डाला जा रहा है, तो मैं कैसे कुंजी को गतिशील बना सकता
हूं

36

आप अपने तानाशाह को चुन सकते हैं और स्ट्रिंग के रूप में बचा सकते हैं।

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)

11
यह सच है, लेकिन रीड और राइट की दर के आधार पर, यह गंभीर ओवरहेड जोड़ सकता है। अचार बनाना एक धीमा ऑपरेशन है
टॉमी

1
कृपया ध्यान दें कि यदि इसका उपयोग उपयोगकर्ता इनपुट के साथ किया जाता है तो आपका सर्वर रिमोट कोड एक्ज़ेन के लिए प्रवण है , pickle.loadsइसका उपयोग केवल 100% विश्वसनीय डेटा पर किया जाना चाहिए
पैराडॉक्सिस

16

दूसरा तरीका: आप 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

यह अजगर प्रकारों को रेडिस प्रकार और इसके विपरीत में परिवर्तित करता है।

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


2
ध्यान दें, RedisWorks hmsetहुड के नीचे का उपयोग करता है यदि आप एक चर को एक चर सेट करते हैं, और इस प्रकार यदि आप करते root.something = {}हैं तो आपको एक DataError मिलेगी, क्योंकि hmsetखाली शब्दकोशों की अनुमति नहीं देता है। मैं इसका उल्लेख करता हूं क्योंकि रेडिस के लिए प्रलेखन आपको यह नहीं बताता है।
१long

दिलचस्प। हाँ यह उपयोग करता है hmset। मैं इस पर गौर करूंगा। @ लॉन्गमोर
सेपरमैन

लेकिन फिर भी, क्या यह शब्दकोश में बाइट्स का समर्थन कर सकता है?
ZettaCircl

12

जैसा कि मूल उत्तर पहले से ही अन्य लोगों द्वारा दिया गया है, मैं इसमें कुछ जोड़ना चाहूंगा।

निम्न मानों के REDISसाथ बुनियादी संचालन करने के लिए आदेश दिए गए HashMap/Dictionary/Mappingहैं।

  1. HGET => एकल कुंजी के लिए रिटर्न मान
  2. एचएसईटी => एकल कुंजी के लिए सेट / अपडेट मूल्य
  3. HMGET => एकल / एकाधिक कुंजियों के लिए लौटाया गया मान
  4. HMSET => कई कुंजी के लिए मान सेट / अद्यतन करता है
  5. HGETALL => मैपिंग में सभी (कुंजी, मान) जोड़े लौटाता है।

redis-pyपुस्तकालय में उनके संबंधित तरीके निम्नलिखित हैं : -

  1. एचजीईटी => हॉज
  2. HSET => hset
  3. HMGET => hmget
  4. एचएमएसईटी => एचएमएसईटी
  5. एचजीईटीएलएल => हॉटल

उपरोक्त सभी सेटर विधियाँ मैपिंग बनाती हैं, यदि यह मौजूद नहीं है। उपरोक्त सभी गेटर विधियाँ त्रुटि / अपवाद नहीं बढ़ाती हैं, यदि मैपिंग में मैपिंग / कुंजी मौजूद नहीं है।

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

मुझे उम्मीद है, यह चीजों को और अधिक स्पष्ट करता है।


आप कैसे मुख्य गतिशील बना सकते हैं
ak3191

11

यदि आप रेडीस में एक अजगर तानाशाह को स्टोर करना चाहते हैं, तो इसे जोंस स्ट्रिंग के रूप में संग्रहीत करना बेहतर है।

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)

De-serialize प्राप्त करते समय इसे json.loads का उपयोग करते हुए

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

प्रकार के बारे में क्या है (उदाहरण के लिए। जेट्स) जो कि जसन कार्यों द्वारा क्रमबद्ध नहीं हैं?

आप उन प्रकारों के लिए एनकोडर / डिकोडर फ़ंक्शन लिख सकते हैं जिन्हें json फ़ंक्शन द्वारा क्रमबद्ध नहीं किया जा सकता है। जैसे। बाइट सरणी के लिए base64 / ascii एनकोडर / डिकोडर फ़ंक्शन लिखना।


मैंने इसे डाउनवोट कर दिया क्योंकि कुछ dicts को JSON से अनुक्रमित नहीं किया जा सकता है, उदाहरण के लिए, बाइट्स मान के साथ dicts।
टॉमी

1
आप एनकोडर / डिकोडर फ़ंक्शन (आवश्यकता के अनुसार, उदाहरण के लिए। base64 / ascii एन्कोडिंग) को उन प्रकारों के लिए लिख सकते हैं जिन्हें डिफ़ॉल्ट रूप से एन्कोडेड / डिकोड नहीं किया जा सकता है।
साजी ज़ेवियर

@ टॉमी - भले ही hmset / hgetall का उपयोग करें, आपको उन प्रकारों को एनकोड / डीकोड करना पड़ सकता है जो रेडिस के लिए समर्थित नहीं हैं।
साजी ज़ेवियर

1
"... बाद का ऑपरेशन O (N) है" के बारे में असहमत। N आपके पास कुंजी के लिए फ़ील्ड की संख्या है। N SET / GET या 1 HGET / HSET करना एक ही जटिलता है। देखें: redis.io/commands/hmset समय-वार, HGET / HSET परमाणु लेनदेन हैं, और इसलिए REDIS द्वारा तेजी से प्रदर्शन किया जाता है। आप सिर्फ रेडिस से पाइथन कोड की जटिलता को आगे बढ़ा रहे हैं।
ZettaCircl

Hmset का लाभ केवल तानाशाही के कुछ उप-भागों को पुनः प्राप्त करने का व्यवसाय है। Json के साथ हम खो देते हैं, इसलिए यह अचार या अन्य चीज़ के रूप में अच्छा है।
जॉर्ज लेइताओ

5

एक विचार कर सकते हैं MessagePack जो redis ने समर्थन किया है।

import msgpack

data = {
    '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]}

Msgpack-python और aioredis का उपयोग करना


4

एक और तरीका जिससे आप इस मामले को देख सकते हैं:

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!

मैंने दक्षता / गति के लिए इसका परीक्षण नहीं किया।


3

रेडिस SET कमांड एक स्ट्रिंग स्टोर करता है, न कि मनमाना डेटा। आप रेडिस एचएसईटी कमांड का उपयोग करने की कोशिश कर सकते हैं ताकि कुछ के साथ एक रेडिस हैश के रूप में तानाशाही को स्टोर किया जा सके

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

लेकिन रेडिस डेटाैटिस और पायथन डेटैटिप काफी ऊपर नहीं हैं। पायथन डाइक को मनमाने ढंग से घोंसला बनाया जा सकता है, लेकिन एक लाल हैश की आवश्यकता होती है कि आपका मूल्य एक स्ट्रिंग है। एक और तरीका जो आप अपना सकते हैं, वह है कि अपने अजगर के डेटा को स्ट्रिंग में बदलना और उसे फिर से स्टोर करना, जैसे कुछ

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

और फिर जब आप स्ट्रिंग को बाहर निकालते हैं तो आपको अजगर ऑब्जेक्ट को फिर से बनाने के लिए इसे पार्स करने की आवश्यकता होगी।


1
वह अपने डेटा को जेन्स में बदल सकता है और रिजल्ट को स्टोर कर सकता है
Narcisse Doudieu Siewe

3

HMSET को पदावनत कर दिया जाता है। अब आप HSET का उपयोग इस प्रकार कर सकते हैं:

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)

धन्यवाद! मैं डॉक्टर को खोजने की कोशिश कर रहा हूं जहां यह सब वर्तनी है। क्या आपको पता है यह कहाँ है। उदाहरण के लिए, दो "नोन्स" क्या हैं।
नीलवैल्ट्स

@NealWalters: HMSET कमांड पेज पर लाइन देखें - पुनर्वितरण चेतावनी के लिए redis.io/commands/hmset
सरसंघ सिंह

0

प्रयास करें rejson-py जो इस पर 2017 के बाद से देखो अपेक्षाकृत नई है परिचय

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

यदि आप वास्तव में रेडिस में डेटा को व्यवस्थित करने का तरीका नहीं जानते हैं, तो मैंने कुछ प्रदर्शन परीक्षण किए, जिसमें परिणाम पार्स करना शामिल है। मेरे द्वारा उपयोग की जाने वाली डिक्टोनरी ( d ) में 437.084 कीज़ (md5 प्रारूप) और इस फॉर्म के मान हैं:

{"path": "G:\tests\2687.3575.json",
 "info": {"f": "foo", "b": "bar"},
 "score": 2.5}

पहला टेस्ट (डेटा को एक रेडिस की-वैल्यू मैपिंग में सम्मिलित करना):

conn.hmset('my_dict', d)  # 437.084 keys added in 8.98s

conn.info()['used_memory_human']  # 166.94 Mb

for key in d:
    json.loads(conn.hget('my_dict', key).decode('utf-8').replace("'", '"'))
    #  41.1 s

import ast
for key in d:
    ast.literal_eval(conn.hget('my_dict', key).decode('utf-8'))
    #  1min 3s

conn.delete('my_dict')  # 526 ms

दूसरा परीक्षण (डेटा को सीधे Redis कुंजियों में सम्मिलित करना):

for key in d:
    conn.hmset(key, d[key])  # 437.084 keys added in 1min 20s

conn.info()['used_memory_human']  # 326.22 Mb

for key in d:
    json.loads(conn.hgetall(key)[b'info'].decode('utf-8').replace("'", '"'))
    #  1min 11s

for key in d:
    conn.delete(key)
    #  37.3s

जैसा कि आप देख सकते हैं, दूसरे परीक्षण में, केवल 'जानकारी' मूल्यों को पार्स किया जाना है, क्योंकि hgetall (कुंजी) पहले से ही एक तानाशाह को लौटाता है, लेकिन एक नेस्टेड नहीं।

और निश्चित रूप से, रेडिस को अजगर के रूप में उपयोग करने का सबसे अच्छा उदाहरण, पहला परीक्षण है

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.