2013-03-14 12 views
5

के मिलान किए गए तत्वों का चयन करें मैं mongoose.js का उपयोग mongodb से पूछताछ करने के लिए कर रहा हूं, लेकिन मुझे लगता है कि मेरी समस्या mongoose.js के लिए विशिष्ट नहीं है।मोंगो डीबी: सबकोलेक्शन

मैं संग्रह में केवल एक रिकॉर्ड है कहते हैं:

var album = new Album({ 
    tracks: [{ 
     title: 'track0', 
     language: 'en', 

    },{ 
     title: 'track1', 
     language: 'en', 
    },{ 
     title: 'track2', 
     language: 'es', 
    }] 
}) 

मैं भाषा क्षेत्र के साथ सभी पटरियों 'एन' के बराबर का चयन करना चाहते, तो मैं दो वेरिएंट की कोशिश की:

Album.find({'tracks.language':'en'}, {'tracks.$': 1}, function(err, albums){ 

और $ elemMatch प्रक्षेपण के साथ एक ही चीज़ से जुड़ा हुआ है:

Album.find({}, {tracks: {$elemMatch: {'language': 'en'}}}, function(err, albums){ 

किसी भी मामले में मुझे एक ही परिणाम मिला है:

{tracks:[{title: 'track0', language: 'en'}, {title: 'track1', language: 'en'}]} 

क्या मैं गलत कर रहा हूँ:

{tracks:[{title: 'track0', language: 'en'}]} 

चयनित album.tracks शीर्षक 'track0' के साथ केवल एक ट्रैक तत्व होते हैं (लेकिन वहाँ दोनों 'track0', 'track1' होनी चाहिए)?

+4

आप कुछ भी गलत नहीं कर रहे हैं, कि अभी जिस तरह उन प्रश्नों काम है - वे केवल पहले मिलान तत्व शामिल हैं। मुझे लगता है कि आप जो चाहते हैं उसे करने के लिए आपको एकत्रीकरण ढांचे का उपयोग करने की आवश्यकता होगी। – JohnnyHK

+0

धन्यवाद, क्या आप मेरी अधिक विशेष युक्ति या कुछ दे सकते हैं? – WHITECOLOR

उत्तर

11

@JohnnyHK की तरह पहले से ही कहा गया है, आपको इसे पूरा करने के लिए एकत्रीकरण ढांचे का उपयोग करना होगा क्योंकि $ और $elemMatch केवल पहला मैच लौटाता है।

db.Album.aggregate(
    // This is optional. It might make your query faster if you have 
    // many albums that don't have any English tracks. Take a larger 
    // collection and measure the difference. YMMV. 
    { $match: {tracks: {$elemMatch: {'language': 'en'}} } }, 

    // This will create an 'intermediate' document for each track 
    { $unwind : "$tracks" }, 

    // Now filter out the documents that don't contain an English track 
    // Note: at this point, documents' 'tracks' element is not an array 
    { $match: { "tracks.language" : "en" } }, 

    // Re-group so the output documents have the same structure, ie. 
    // make tracks a subdocument/array again 
    { $group : { _id : "$_id", tracks : { $addToSet : "$tracks" } }} 
); 

आप केवल पहली अभिव्यक्ति के साथ कि कुल क्वेरी कोशिश करने के लिए और फिर कैसे उत्पादन बदल गया है देखने के लिए लाइन द्वारा भाव पंक्ति जोड़ें चाह सकते हैं:

यहाँ कैसे। यह समझना विशेष रूप से महत्वपूर्ण है कि $unwind मध्यवर्ती दस्तावेज़ बनाता है जिसे बाद में $group और $addToSet का उपयोग करके फिर से विलय कर दिया जाता है।

परिणाम:

> db.Album.aggregate(
    { $match: {tracks: {$elemMatch: {'language': 'en'}} } }, 
    { $unwind : "$tracks" }, 
    { $match: { "tracks.language" : "en" } }, 
    { $group : { _id : "$_id", tracks : { $addToSet : "$tracks" } }} ); 
{ 
    "result" : [ 
      { 
        "_id" : ObjectId("514217b1c99766f4d210c20b"), 
        "tracks" : [ 
          { 
            "title" : "track1", 
            "language" : "en" 
          }, 
          { 
            "title" : "track0", 
            "language" : "en" 
          } 
        ] 
      } 
    ], 
    "ok" : 1 
} 
+0

बहुत बहुत धन्यवाद! – WHITECOLOR

+0

यदि आप चयनित ट्रैक को प्रतिबंधित करने के लिए ऑल्नी शीर्षक फ़ील्ड (भाषा फ़ील्ड की तरह कोई अन्य नहीं) को ध्यान में रखते हैं तो एक और संबंधित प्रश्न। – WHITECOLOR

+0

@mnemosyn मैंने अपनी संबंधित समस्या पर इस समाधान की कोशिश की और यह काम किया। अब मुझे वापस जाना है और समझना है! – carbontax

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