यहां मूल अवधारणा यह है कि शर्तों के लिए सरणी तत्वों को "फ़िल्टर" करने के लिए शर्तों को लागू करने के लिए आपको एकत्रीकरण ढांचे की आवश्यकता है। उपलब्ध संस्करण के आधार पर विभिन्न तकनीकें हैं जिन्हें लागू किया जा सकता है।
सभी मामलों में यह परिणाम है:
{
"_id" : ObjectId("593921425ccc8150f35e7664"),
"user1" : 1,
"user2" : 4,
"messages" : {
"sender" : 1,
"datetime" : ISODate("2017-06-09T10:04:50Z"),
"body" : "hiii 1"
}
}
{
"_id" : ObjectId("593921425ccc8150f35e7663"),
"user1" : 1,
"user2" : 3,
"messages" : {
"sender" : 1,
"datetime" : ISODate("2017-06-10T10:04:50Z"),
"body" : "hiii 2"
}
}
{
"_id" : ObjectId("593921425ccc8150f35e7662"),
"user1" : 1,
"user2" : 2,
"messages" : {
"sender" : 1,
"datetime" : ISODate("2017-06-08T10:04:50Z"),
"body" : "hiii 0"
}
}
MongoDB 3.4 और इसके बाद के संस्करण
db.chat.aggregate([
{ "$match": { "messages.sender": 1 } },
{ "$replaceRoot": {
"newRoot": {
"$let": {
"vars": {
"messages": {
"$filter": {
"input": "$messages",
"as": "m",
"cond": { "$eq": [ "$$m.sender", 1 ] }
}
},
"maxDate": {
"$max": {
"$map": {
"input": {
"$filter": {
"input": "$messages",
"as": "m",
"cond": { "$eq": [ "$$m.sender", 1 ] }
}
},
"as": "m",
"in": "$$m.datetime"
}
}
}
},
"in": {
"_id": "$_id",
"user1": "$user1",
"user2": "$user2",
"messages": {
"$arrayElemAt": [
{ "$filter": {
"input": "$$messages",
"as": "m",
"cond": { "$eq": [ "$$m.datetime", "$$maxDate" ] }
}},
0
]
}
}
}
}
}}
])
यह सबसे कारगर तरीका है जो $replaceRoot<का लाभ उठाता है /कोड>
जो हमें <का उपयोग करके "प्रतिस्थापित" संरचना में उपयोग करने के लिए चर घोषित करने की अनुमति देता है। कोड>$लेट
. यहां मुख्य लाभ यह है कि इसके लिए केवल "दो" पाइपलाइन चरणों की आवश्यकता होती है।
आपके द्वारा उपयोग की जाने वाली सरणी सामग्री से मिलान करने के लिए $filter
कोड>
जहां आप $eq
लागू करते हैं
"प्रेषक"
. के मान का परीक्षण करने के लिए तार्किक संचालन . जहां कंडीशन मेल खाती है, वहां केवल मैचिंग ऐरे एंट्रीज ही वापस आती हैं।
उसी का उपयोग करना $filter
ताकि केवल मेल खाने वाली "प्रेषक" प्रविष्टियों पर विचार किया जा सके, फिर हम $अधिकतम
"datetime"
. में मानों के लिए "फ़िल्टर की गई" सूची पर . $अधिकतम
]5
मान शर्तों के अनुसार "नवीनतम" तिथि है।
हम यह मान चाहते हैं ताकि हम बाद में "फ़िल्टर किए गए" सरणी से लौटाए गए परिणामों की तुलना इस "maxDate" से कर सकें। "in"
. के अंदर क्या होता है $let
का ब्लॉक
जहां फ़िल्टर की गई सामग्री के लिए पहले घोषित किए गए दो "चर" और "maxDate" को फिर से $filter
वापस करने के लिए केवल वही मान होना चाहिए जो "नवीनतम तिथि" वाली दोनों शर्तों को पूरा करता हो।
चूँकि आप केवल "एक" परिणाम चाहते हैं, हम $arrayElemAt का उपयोग करते हैं
सरणी के बजाय मान का उपयोग करने के लिए।
मोंगोडीबी 3.2
db.chat.aggregate([
{ "$match": { "messages.sender": 1 } },
{ "$project": {
"user1": 1,
"user2": 1,
"messages": {
"$filter": {
"input": "$messages",
"as": "m",
"cond": { "$eq": [ "$$m.sender", 1 ] }
}
},
"maxDate": {
"$max": {
"$map": {
"input": {
"$filter": {
"input": "$messages",
"as": "m",
"cond": { "$eq": [ "$$m.sender", 1 ] }
}
},
"as": "m",
"in": "$$m.datetime"
}
}
}
}},
{ "$project": {
"user1": 1,
"user2": 1,
"messages": {
"$arrayElemAt":[
{ "$filter": {
"input": "$messages",
"as": "m",
"cond": { "$eq": [ "$$m.datetime", "$maxDate" ] }
}},
0
]
}
}}
])
यह मूल रूप से वर्णित प्रक्रिया के समान है, लेकिन $ के बिना रिप्लेसरूट
पाइपलाइन चरण, हमें दो में आवेदन करने की आवश्यकता है $project
कोड>
चरण। इसका कारण यह है कि हमें अंतिम $फ़िल्टर
, और यह कंपाउंड स्टेटमेंट में करने के लिए उपलब्ध नहीं है, इसलिए इसके बजाय हम पाइपलाइनों को विभाजित करते हैं। इसका संचालन की कुल लागत पर बहुत कम प्रभाव पड़ता है।
MongoDB 2.6 से 3.0 में हम <को छोड़कर यहां अधिकांश तकनीक का उपयोग कर सकते हैं। कोड>$arrayElemAt
और या तो एकल प्रविष्टि के साथ "सरणी" परिणाम स्वीकार करें या में डालें $अनविंड
अब एकल प्रविष्टि क्या होनी चाहिए, इससे निपटने के लिए चरण।
MongoDB पुराने संस्करण
db.chat.aggregate([
{ "$match": { "messages.sender": 1 } },
{ "$unwind": "$messages" },
{ "$match": { "messages.sender": 1 } },
{ "$sort": { "_id": 1, "messages.datetime": -1 } },
{ "$group": {
"_id": "$_id",
"user1": { "$first": "$user1" },
"user2": { "$first": "$user2" },
"messages": { "$first": "$messages" }
}}
])
हालांकि यह संक्षिप्त दिखता है, यह अब तक का सबसे महंगा ऑपरेशन है। यहां आपको $unwind
का इस्तेमाल करना चाहिए
सरणी तत्वों के लिए शर्तों को लागू करने के लिए। यह एक बहुत ही महंगी प्रक्रिया है क्योंकि यह प्रत्येक सरणी प्रविष्टि के लिए प्रत्येक दस्तावेज़ की एक प्रति तैयार करता है, और अनिवार्य रूप से आधुनिक ऑपरेटरों द्वारा प्रतिस्थापित किया जाता है जो "फ़िल्टरिंग" के मामले में इससे बचते हैं।
दूसरा $match
यहां चरण किसी भी तत्व (अब "दस्तावेज़") को त्याग देता है जो "प्रेषक" स्थिति से मेल नहीं खाता। फिर हम एक $sort
लागू करते हैं
_id
. द्वारा प्रत्येक दस्तावेज़ के लिए "नवीनतम" तिथि को शीर्ष पर रखने के लिए , इसलिए दो "सॉर्ट" कुंजियाँ।
अंत में हम $group
लागू करते हैं
केवल मूल दस्तावेज़ को संदर्भित करने के लिए, $first का उपयोग करके
"शीर्ष पर" तत्व प्राप्त करने के लिए संचायक के रूप में।