2017 अपडेट
इस तरह के एक अच्छी तरह से रखा गया प्रश्न आधुनिक प्रतिक्रिया का पात्र है। अनुरोधित सरणी फ़िल्टरिंग वास्तव में आधुनिक मोंगोडीबी रिलीज 3.2 में केवल $match
के माध्यम से किया जा सकता है और $project
पाइपलाइन चरण, मूल सादे क्वेरी ऑपरेशन की तरह।
db.accounts.aggregate([
{ "$match": {
"email" : "[email protected]",
"groups": {
"$elemMatch": {
"name": "group1",
"contacts.localId": { "$in": [ "c1","c3", null ] }
}
}
}},
{ "$addFields": {
"groups": {
"$filter": {
"input": {
"$map": {
"input": "$groups",
"as": "g",
"in": {
"name": "$$g.name",
"contacts": {
"$filter": {
"input": "$$g.contacts",
"as": "c",
"cond": {
"$or": [
{ "$eq": [ "$$c.localId", "c1" ] },
{ "$eq": [ "$$c.localId", "c3" ] }
]
}
}
}
}
}
},
"as": "g",
"cond": {
"$and": [
{ "$eq": [ "$$g.name", "group1" ] },
{ "$gt": [ { "$size": "$$g.contacts" }, 0 ] }
]
}
}
}
}}
])
यह $filter
. का उपयोग करता है और $map
ऑपरेटरों को केवल शर्तों को पूरा करने के लिए सरणियों से तत्वों को वापस करने के लिए, और प्रदर्शन के लिए $unwind
का उपयोग करने से कहीं बेहतर है . चूंकि पाइपलाइन चरण प्रभावी रूप से एक .find()
से "क्वेरी" और "प्रोजेक्ट" की संरचना को प्रतिबिंबित करते हैं। संचालन, यहां प्रदर्शन मूल रूप से इस तरह और संचालन के बराबर है।
ध्यान दें कि जहां इरादा वास्तव में काम करना है "सभी दस्तावेज़ों में" "एक" के बजाय "एकाधिक" दस्तावेज़ों में से विवरण एक साथ लाने के लिए, इसके लिए आमतौर पर कुछ प्रकार के $unwind
की आवश्यकता होगी ऐसा करने के लिए ऑपरेशन, जैसे कि "ग्रुपिंग" के लिए ऐरे आइटम्स को एक्सेस करने योग्य बनाना।
यह मूल रूप से दृष्टिकोण है:
db.accounts.aggregate([
// Match the documents by query
{ "$match": {
"email" : "[email protected]",
"groups.name": "group1",
"groups.contacts.localId": { "$in": [ "c1","c3", null ] },
}},
// De-normalize nested array
{ "$unwind": "$groups" },
{ "$unwind": "$groups.contacts" },
// Filter the actual array elements as desired
{ "$match": {
"groups.name": "group1",
"groups.contacts.localId": { "$in": [ "c1","c3", null ] },
}},
// Group the intermediate result.
{ "$group": {
"_id": { "email": "$email", "name": "$groups.name" },
"contacts": { "$push": "$groups.contacts" }
}},
// Group the final result
{ "$group": {
"_id": "$_id.email",
"groups": { "$push": {
"name": "$_id.name",
"contacts": "$contacts"
}}
}}
])
यह एक से अधिक मिलान पर "सरणी फ़िल्टरिंग" है जो .find()
की मूल प्रक्षेपण क्षमताएं हैं नहीं कर सकता।
आपके पास "नेस्टेड" सरणियाँ हैं इसलिए आपको $unwind
process को संसाधित करने की आवश्यकता है दो बार। अन्य कार्यों के साथ।