यदि आपको क्रम में कुछ इस तरह की गणना करने की आवश्यकता है, क्रमबद्ध क्रम को निर्धारित करने वाले सरणी से "फ़िल्टर की गई" सामग्री के साथ, तो आप सबसे अच्छा कुछ करते हैं .aggregate()
इस तरह से सॉर्ट वैल्यू को फिर से आकार देने और निर्धारित करने के लिए:
db.collection.aggregate([
// Pre-filter the array elements
{ "$project": {
"tags": 1,
"score": {
"$setDifference": [
{ "$map": {
"input": "$tags",
"as": "tag",
"in": {
"$cond": [
{ "$eq": [ "$$el.id", "t1" ] },
"$$el.score",
false
]
}
}},
[false]
]
}
}},
// Unwind to denormalize
{ "$unwind": "$score" },
// Group back the "max" score
{ "$group": {
"_id": "$_id",
"tags": { "$first": "$tags" },
"score": { "$max": "$score" }
}},
// Sort descending by score
{ "$sort": { "score": -1 } }
])
जहां पाइपलाइन के पहले भाग का उपयोग "स्कोर" के केवल उन मानों के लिए सरणी सामग्री (साथ ही मूल फ़ील्ड को रखते हुए) को "पूर्व-फ़िल्टर" करने के लिए किया जाता है जहां आईडी "t1" के बराबर होती है। यह $map
को प्रोसेस करके किया जाता है
जो प्रत्येक तत्व के लिए $cond
यह निर्धारित करने के लिए कि उस तत्व के लिए "स्कोर" वापस करना है या गलत
।
$setDifference
ऑपरेशन एकल तत्व सरणी की तुलना करता है [false]
जो किसी भी गलत
. को प्रभावी ढंग से हटा देता है $map
. से लौटाए गए मान . एक "सेट" के रूप में, यह डुप्लिकेट प्रविष्टियों को भी हटा देता है, लेकिन यहाँ क्रमबद्ध उद्देश्य के लिए यह एक अच्छी बात है।
आपके द्वारा संसाधित किए जाने वाले मानों के लिए सरणी कम और पुन:आकार देने के साथ $unwind
व्यक्तिगत तत्वों के रूप में मूल्यों से निपटने के लिए अगले चरण के लिए तैयार। $group
चरण अनिवार्य रूप से लागू होता है $max
फ़िल्टर किए गए परिणामों में निहित उच्चतम मान वापस करने के लिए "स्कोर" पर।
फिर यह केवल $sortको लागू करने की बात है। कोड>
दस्तावेजों को ऑर्डर करने के लिए निर्धारित मूल्य पर। स्वाभाविक रूप से यदि आप इसे दूसरे तरीके से चाहते थे तो $min का उपयोग करें
और इसके बजाय आरोही क्रम में क्रमबद्ध करें।
बेशक एक $match
जोड़ें
यदि आप वास्तव में चाहते हैं तो शुरुआत के चरण में वे दस्तावेज़ हैं जिनमें वास्तव में id
. के लिए "t1" मान शामिल हैं टैग के भीतर। लेकिन फ़िल्टर किए गए परिणामों पर छँटाई के लिए वह हिस्सा कम से कम प्रासंगिक है जिसे आप प्राप्त करना चाहते हैं।
गणना करने का विकल्प यह सब करना है जब आप दस्तावेज़ों में सरणी में प्रविष्टियाँ लिखते हैं। कुछ गड़बड़ है, लेकिन यह कुछ इस तरह है:
db.collection.update(
{ "_id": docId },
{
"$push": { "tags": { "id": "t1", "score": 60 } },
"$max": { "maxt1score": 60 },
"$min": { "mint1score": 60 }
}
)
यहां $max
अद्यतन ऑपरेटर केवल निर्दिष्ट फ़ील्ड के लिए मान सेट करता है यदि नया मान मौजूदा मान से अधिक है या अन्यथा कोई संपत्ति अभी तक मौजूद नहीं है। $min
, जहां इससे कम होने पर ही इसे नए मान से बदल दिया जाएगा।
यह निश्चित रूप से दस्तावेजों में विभिन्न अतिरिक्त गुणों को जोड़ने का प्रभाव होगा, लेकिन अंतिम परिणाम छँटाई बहुत सरल है:
db.collection.find().sort({ "maxt1score": -1 })
और यह एकत्रीकरण पाइपलाइन के साथ गणना करने की तुलना में बहुत तेज़ चलने वाला है।
तो डिजाइन सिद्धांतों पर विचार करें। सरणियों में संरचित डेटा जहां आप छँटाई के लिए फ़िल्टर और युग्मित परिणाम चाहते हैं, इसका मतलब है कि किस मान को क्रमबद्ध करना है, यह निर्धारित करने के लिए रन-टाइम पर गणना करना। .update()
. पर दस्तावेज़ में अतिरिक्त गुण जोड़ना इसका मतलब है कि आप सीधे परिणामों को क्रमबद्ध करने के लिए उन गुणों को संदर्भित कर सकते हैं।