2012-01-01 15 views
35

यहाँ में दुकान वस्तुओं बात है - मैं एक निश्चित कुंजी के अंतर्गत देशी जे एस (Node.js) redis में वस्तुओं (फ्लैश सॉकेट संदर्भ) संग्रहीत करना चाहते हैं। जब मैं इसे सरल client.set() के साथ करता हूं तो यह एक स्ट्रिंग के रूप में संग्रहीत होता है। जब मैं मूल्य प्राप्त करने का प्रयास करता हूं तो मुझे [object Object] मिलता है - बस एक स्ट्रिंग।Node.js redis

इस काम को पाने का कोई मौका? यहाँ मेरी कोड है:

addSocket : function(sid, socket) { 
    client.set(sid, socket); 
    }, 

    getSocket : function(sid) { 
    client.get(sid, function(err, reply) { 
     // cant't get an object here. All I get is useless string 
    }); 
    }, 
+0

उस स्ट्रिंग में क्या है? – clyfe

+0

आप डेटाबेस के कुछ रूपों में जावास्क्रिप्ट के संदर्भों को संग्रहीत नहीं कर सकते हैं क्योंकि सर्वर – Raynos

+0

@clyfe नीचे जाने पर ऑब्जेक्ट्स गायब हो जाता है: [ऑब्जेक्ट ऑब्जेक्ट] – Pono

उत्तर

19

Downvoters: संदर्भ यहाँ आदेश और मनमाने ढंग से वस्तुओं को स्टोर करने की क्षमता निर्धारित है।

नहीं, आप ऐसा नहीं कर सकते। आपको इस तथ्य को स्वीकार करना चाहिए कि रेडिस सबकुछ एक स्ट्रिंग के रूप में संग्रहीत करता है (प्रोटोकॉल टेक्स्ट-आधारित है, सब के बाद)। रेडिस कुछ अनुकूलन कर सकता है और कुछ मानों को पूर्णांक में परिवर्तित कर सकता है, लेकिन यह आपका व्यवसाय है, न कि आपका।

यदि आप रेडिस में मनमाने ढंग से ऑब्जेक्ट्स स्टोर करना चाहते हैं, तो सुनिश्चित करें कि आप उन्हें पुनर्प्राप्त करने के बाद सहेजने और डी-क्रमबद्ध करने से पहले क्रमबद्ध करें।

मुझे यकीन नहीं है कि क्या आप सॉकेट ऑब्जेक्ट्स के साथ ऐसा कर सकते हैं। वे बस एक सिस्टम संसाधन (एक खुला कनेक्शन) का वर्णन करते हैं, सब के बाद (उदाहरण के लिए टीसीपी सॉकेट)। यदि आप विवरण को क्रमबद्ध करने और इसे किसी अन्य मशीन पर deserialize करने के लिए प्रबंधन करते हैं, तो उस अन्य मशीन में कनेक्शन नहीं होगा।

+3

यह सुनिश्चित नहीं है कि 2012 में यह कैसा रहा, लेकिन कम से कम अब 2016 में रेडीस ** करता है * * मनमानी वस्तुओं को स्टोर करें, यह ** स्ट्रिंग के रूप में ** स्टोर नहीं करता है। आपको उस कार्यक्षमता का उपयोग करने के लिए बस विभिन्न कमांड/विधियों का उपयोग करने की आवश्यकता है। बेहतर समाधान के लिए जेसन लवमैन का जवाब देखें: http://stackoverflow.com/a/21490063/130691 – JMTyler

+2

@JMTyler: दस्तावेज़ों के लिंक? Redis __arbitrary__ वस्तुओं को स्टोर नहीं करता है। बस कुछ पूर्व निर्धारित प्रकार (स्ट्रिंग, हैश, सूची, आदि)। और यदि आप 'SET' कमांड के माध्यम से कुछ संग्रहीत करते हैं, तो इसे स्ट्रिंग के रूप में संग्रहीत किया जाएगा। इस के आसपास कोई रास्ता नहीं है। –

+0

हां, एसईटी एक स्ट्रिंग के रूप में स्टोर करता है, लेकिन जाहिर है कि रेडिस का एकमात्र कमांड नहीं है। आप दावा नहीं कर सकते कि एसईटी कैसे काम करता है यह है कि रेडिस कैसे काम करता है। आपके द्वारा उपयोग की जाने वाली भाषा/प्लेटफ़ॉर्म के आधार पर 'हैश' ** ** वस्तु के लिए एक और शब्द है, इसलिए मुझे नहीं लगता कि आपका तर्क क्या है। तथ्य यह है कि आप हैश का उल्लेख करते हैं, इसका मतलब है कि आप स्पष्ट रूप से जानते हैं कि आप केवल तारों की तुलना में अधिक जटिल डेटा स्टोर कर सकते हैं। – JMTyler

87

के बाद से सॉकेट प्रकार 'वस्तु' की है, तो आप भंडारण और जब सॉकेट पुन: प्राप्त करने, एक वस्तु के लिए इसे वापस बदलने की आवश्यकता से पहले एक स्ट्रिंग के लिए वस्तु कन्वर्ट करने के लिए की जरूरत है। आप

JSON.stringify(socket) 

एक स्ट्रिंग में बदलने के लिए उपयोग कर सकते हैं और

JSON.parse(socketstr) 

एक वस्तु को वापस परिवर्तित करने के लिए।

+8

अब यह एक जवाब है! आप कुछ नहीं कर सकते हैं कभी जवाब नहीं है। टीएनएक्स शॉन। – Maziyar

+1

यह स्वीकार्य उत्तर होना चाहिए। – moeiscool

+0

यह स्वीकार्य उत्तर क्यों नहीं है? एक अपवित्र ले लो। –

3

मुझे विश्वास है कि जब आप ऑब्जेक्ट को स्टोर करते हैं, तो आंतरिक रूप से, object.toString() भंडारण से पहले कहा जाता है और यह वह मान है जो संग्रहीत किया जाता है।

({a: 1}).toString() # "[object Object]" 

आपको जो करना है वह JSON.encode और JSON.parse का उपयोग करना है।

आप स्टोर (छुपा, बाइनरी) संदर्भों को स्टोर नहीं कर सकते हैं।
अन्यथा, आप पूर्णांक और सॉकेट, और स्टोर पूर्णांक के बीच एक पत्राचार करने में सक्षम हो सकते हैं।

-1

आप इस तरह की तकनीक का उपयोग कर जावास्क्रिप्ट ऑब्जेक्ट का संदर्भ सहेज सकते हैं। असल में, यह ऑब्जेक्ट.प्रोटोटाइप (इसमें नहीं है) को बढ़ाता है और आप रैड (} को कस्टम संदर्भ जोड़ने के लिए radd() को कॉल कर सकते हैं, फिर ऑब्जेक्ट को rget() से पुनर्प्राप्त करें। "संदर्भ" एक स्ट्रिंग है इसलिए यह रेडिस में ठीक से फिट होगा। इसका मतलब है कि आपको डेटाबेस में प्रतिलिपि बनाने/प्राप्त करने के लिए .stringify() और .parse() को नहीं करना होगा। हालांकि, ऑब्जेक्ट का डेटा नष्ट हो जाएगा जब नोड इसके क्रमबद्ध होने तक बंद हो जाता है।

var OBJECT = Object.prototype; 
OBJECT.rhash = {}; 
OBJECT.rset = function(id, object) { 
    OBJECT.rhash[id] = object; 
    return id; 
}; 
OBJECT.rget = function(id) { 
    return OBJECT.rhash[id]; 
}; 

var dog = { 
    name: "Skippy", 
    food: "Bacon", 
    bark: function() { 
    alert(this.name + "!"); 
    } 
}; 

var id = OBJECT.rset("a123", dog); 
var ref = OBJECT.rget("a123"); 
ref.bark(); 
+7

'ऑब्जेक्ट.प्रोटोटाइप' को संशोधित न करें! – Eric

+0

आपको ऑब्जेक्ट.प्रोटोटाइप में इसे बाध्य करने की आवश्यकता क्यों है और केवल हैश = {}, हैश [कुंजी] = ऑब्जेक्ट करने के बजाय इन्हें प्राप्त/सेट विधियां बनाएं? –

24

क्लस्टर उदाहरणों में डेटा साझा करने के लिए नीचे दिया गया समाधान रेडिस का उपयोग करने के पूरे बिंदु को हल नहीं करता है। रेडिस में एक इंस्टेंस-विशिष्ट आईडी संग्रह करना किसी अन्य उदाहरण के लिए व्यर्थ होगा जो उस आईडी का उपयोग करने का प्रयास करता है।

हालांकि, वहाँ "hmset" जो एक वस्तु के साथ कहा जा सकता है है और यह एक ही कुंजी में एक अलग redis क्षेत्र के रूप में प्रत्येक वस्तु के क्षेत्र सेट हो जाएगा।और जब आप hgetall को कॉल करते हैं तो इसे वापस ऑब्जेक्ट में परिवर्तित कर दिया जाएगा। दुर्भाग्यवश, मुझे नहीं लगता कि यह किसी ऑब्जेक्ट के भीतर नेस्टेड ऑब्जेक्ट्स या सरणी को संभालता है, केवल साधारण गुण जिनके मान "toString()" द्वारा संग्रहीत किए जा सकते हैं।

तो जैसे

client.hmset("myhashkey",{a:1, b:2, c:'xxx'}) 

एक वस्तु महान काम करता है और

client.hmget("myhashkey", function(obj) { 
    console.log(obj); 
}); 
नहीं

के लिए बहुत बहुत के साथ प्राप्त किया जा सकता है:

client.hmset("myhashkeynested",{a:1, b:2, c:'xxx', d: { d1: 'x', d2: 'y'}}); 
+4

द्वारा पुनर्प्राप्त: 'client.hgetall (" the-key-name ", फ़ंक्शन (त्रुटि, obj) {// ...}) ',' hmget' के लिए 'फ़ील्ड नाम' की आवश्यकता है। –

+0

इस उत्तर को अधिक upvotes की जरूरत है! स्वीकृत उत्तर गलत है। – JMTyler

+2

@ जेएम टाइलर: यह मनमाने ढंग से जेएस ऑब्जेक्ट्स (सॉकेट, इस मामले में) को संग्रहीत करने में मदद नहीं करेगा। –

-2

अच्छी तरह से करता है, तो आप इसके बारे में सोचते जावास्क्रिप्ट वस्तुओं रहे हैं कुंजियां जो मान हैं अन्य वस्तुओं का संदर्भ दे सकती हैं, और संभवतः देशी वस्तुओं के सॉकेट के मामले में। तो यदि लालसा निष्पादित जावास्क्रिप्ट से बाहरी है तो वह उस ऑब्जेक्ट के संदर्भ को संग्रहीत करने में सक्षम कैसे होगा?

// a and b exist inside the executing javascript, not in the external O/S 
a = {} 
b = {} 

var obj = { 
    'one': a, 
    'two': b 
} 

// how can redis possibly store references to obj, a or b when this application exits? 
redis.set('obj', obj) 

// same as.. 
redis.set('obj', obj.toString()) /*or*/ redis.set('obj', "" + obj) 

// same as.. 
redis.set('obj', "[object Object]") 


// the trick is to stringify the object 
redis.set('obj', JSON.stringify(obj)) 

// same as.. 
redis.set('obj', "{'one':{},'two':{}}") 

// here redis does not have to store the actual object references but rather a json string representing the object 

// this could also work 
redis.set('obj', "{'one':a,'two':b}") 

// where you would then do: 
obj = eval(redis.get('obj')) 
// provided that a and b have already been initialized 
+1

उपयोग eval हमेशा एक बुरा विचार है – Mauro

6

मैंने यह भी पाया इस, एक अविश्वसनीय रूप से उपयोगी उपकरण विशेष रूप से अगर आप अपने सामने के अंत के लिए एक एपीआई से JSON channeling हैं:

node-redis-jsonify

आप एक बड़ी ब्लॉक मिल रहा है तो JSON का और एक विशिष्ट हैश के रूप में स्टोर नहीं किया जा सकता है, इसे संग्रहीत करते समय इसे स्ट्रिंग करने से आपको "[ऑब्जेक्ट ऑब्जेक्ट]" के बजाय पूरे जेसन को पुनर्प्राप्त करने की अनुमति मिल जाएगी।