2015-10-17 14 views
5

मैं उन तत्वों की खोज करने के लिए MongoDB का उपयोग कर रहा हूं जिनमें सूचियों की एक सूची है जहां सूची में कम से कम एक आइटम खोज पैरामीटर से मेल खाता है।MongoDB सूचियों की सूची में मूल्य पाएं

यह वर्तमान में मौजूद संरचना का एक उदाहरण है।

{ 
    "Item 1":{ 
     "data":[ 
     ["green", 1] 
     ] 
    }, 
    "Item 2":{ 
     "data":[ 
     ["blue", 9], 
     ["green", 1] 
     ] 
    } 
} 

मैं सभी आइटम नहीं हैं कि मूल्य "हरी" डेटा सूची में खोजना चाहते हैं।

my_data.find({'data': {'$in': ['green']}}) 

हालांकि, कोई परिणाम नहीं दिए जाते हैं:

मैं वर्तमान में इस किया है।

+1

यह मदद कर सकता है। http://stackoverflow.com/questions/17303833/mongodb-nested-array-query – lostintranslation

उत्तर

5

आप किसी भी पूछे तत्वों और "डाटा" रास्ता है कि आप यहाँ खोज करने की आवश्यकता के "शीर्ष स्तरीय" नहीं है के लिए एक "प्रत्यक्ष पथ" की जरूरत है, बल्कि यह "आइटम 1" या "आइटम 2 है "दस्तावेज़ और" डेटा "के भीतर इसका उप-तत्व है।

बुनियादी मामले "dot notation" जहां जड़ तत्व "के नाम से" कर रहे हैं कम से कम संभवतः अस्तित्व के लिए उपयोग करने के लिए है, और यह भी ध्यान दें कि $in ऑपरेटर, बस एक सरणी के भीतर एक मूल्य के मैच के लिए आवश्यक नहीं है के बाद से MongoDB परवाह नहीं है। लेकिन अगर आप एक नेस्टेड $elemMatch बजाय की आवश्यकता होगी:

db.my_data.find({ 
    "$or": [ 
     { "Item 1.data": { 
      "$elemMatch": { 
       "$elemMatch": { "$eq": "green" } 
      } 
     }}, 
     { "Item 2.data": { 
      "$elemMatch": { 
       "$elemMatch": { "$eq": "green" } 
      } 
     }} 
    ] 
}) 

कोई एक पूर्ववर्ती पथ का एक हिस्सा मिलान इसलिए यह एक $or हालत के भीतर पूरा पथ राज्य करने के लिए प्रत्येक संभव पथ खोज करने के लिए आवश्यक है के लिए "वाइल्डकार्ड" कर रहे हैं दस्तावेज़।

तो सभी संभव पहले से जुड़ा हुआ चाबियाँ लिखने मिलान के लिए तर्क निर्धारित करने के लिए व्यावहारिक नहीं है, तो अपने ही अन्य दृष्टिकोण $where साथ जावास्क्रिप्ट मूल्यांकन उपयोग कर रहा है:

db.my_data.find(function() { 
    var doc = this; 
    delete doc._id; 

    var matched = false; 
    for (k in doc) { 
     matched = doc[k].data.some(function(el) { 
      return el.some(function(inner) { 
       return inner === "green"; 
      }); 
     }); 
     if (matched) break; 
    } 
    return matched; 
}) 

या उस तर्क के कुछ बदलाव करने के लिए वास्तव में संभव का परीक्षण "डेटा" सरणी वाले तत्वों को आपके "हरे" मान को रखने के लिए। यह एक अच्छा समाधान नहीं है क्योंकि $where को स्थिति का मूल्यांकन करने के लिए प्रत्येक दस्तावेज़ पर निष्पादन की आवश्यकता होती है और इसलिए परिणामों को फ़िल्टर करने के लिए इंडेक्स का उपयोग नहीं किया जा सकता है। इसका मतलब है कि पूरे संग्रह को स्कैन करना और मूल रूप से सबसे धीमा दृष्टिकोण है।

इसके अलावा सिर्फ लेखन के रूप में अन्यथा function() सामग्री सिर्फ एक "स्ट्रिंग" के रूप में बहस में $where को pymongo या अन्य भाषा चालकों के लिए प्रस्तुत किया जाता है करने के लिए "खोल शॉर्टकट" दिखा रहा है, लेकिन बुनियादी संदर्भ है कि यह जावा स्क्रिप्ट कोड है कि सर्वर पर मूल्यांकन किया जाता है।

बेहतर अभी तक अपना दस्तावेज़ बदलना है, इसलिए उस तत्व के लिए हमेशा एक सतत मार्ग है जिसे आप क्वेरी करना चाहते हैं। जैसे:

{ 
    "items": [ 
     { "name": "Item 1", "data": [["green", 1]] }, 
     { "name": "Item 2", "data": [["blue", 9], ["green", 1]] } 
    ] 
} 

तो फिर तुम सिर्फ इस सरल प्रश्न जारी कर सकते हैं:

db.my_data.find({ "items.data": { "$elemMatch": { "$elemMatch": { "$eq": "green" } } } }) 

"पथ" हमेशा की तरह "items.data" है यह सिर्फ उस पथ सभी तत्वों का परीक्षण करने के लिए एक एकल condtion की अनुमति देता है

+0

वास्तव में व्यापक उत्तर के लिए धन्यवाद। यह एक बड़ी मदद थी। – Gunther

संबंधित मुद्दे