एकत्रीकरण ढांचे का उपयोग करके ऐसा करने के कुछ तरीके हैं
उदाहरण के लिए डेटा का एक साधारण सेट:
{
"_id" : ObjectId("538181738d6bd23253654690"),
"movies": [
{ "_id": 1, "rating": 5 },
{ "_id": 2, "rating": 6 },
{ "_id": 3, "rating": 7 }
]
},
{
"_id" : ObjectId("538181738d6bd23253654691"),
"movies": [
{ "_id": 1, "rating": 5 },
{ "_id": 4, "rating": 6 },
{ "_id": 2, "rating": 7 }
]
},
{
"_id" : ObjectId("538181738d6bd23253654692"),
"movies": [
{ "_id": 2, "rating": 5 },
{ "_id": 5, "rating": 6 },
{ "_id": 6, "rating": 7 }
]
}
एक उदाहरण के रूप में पहले "उपयोगकर्ता" का उपयोग करते हुए, अब आप यह जानना चाहते हैं कि क्या अन्य दो उपयोगकर्ताओं में से कम से कम दो समान फिल्में हैं।
MongoDB 2.6 और उससे ऊपर के लिए आप बस $setIntersection
ऑपरेटर के साथ $size
ऑपरेटर:
db.users.aggregate([
// Match the possible documents to reduce the working set
{ "$match": {
"_id": { "$ne": ObjectId("538181738d6bd23253654690") },
"movies._id": { "$in": [ 1, 2, 3 ] },
"$and": [
{ "movies": { "$not": { "$size": 1 } } }
]
}},
// Project a copy of the document if you want to keep more than `_id`
{ "$project": {
"_id": {
"_id": "$_id",
"movies": "$movies"
},
"movies": 1,
}},
// Unwind the array
{ "$unwind": "$movies" },
// Build the array back with just `_id` values
{ "$group": {
"_id": "$_id",
"movies": { "$push": "$movies._id" }
}},
// Find the "set intersection" of the two arrays
{ "$project": {
"movies": {
"$size": {
"$setIntersection": [
[ 1, 2, 3 ],
"$movies"
]
}
}
}},
// Filter the results to those that actually match
{ "$match": { "movies": { "$gte": 2 } } }
])
यह अभी भी MongoDB के पुराने संस्करणों में संभव है, जिनमें वे ऑपरेटर नहीं हैं, बस कुछ और चरणों का उपयोग करके:
db.users.aggregate([
// Match the possible documents to reduce the working set
{ "$match": {
"_id": { "$ne": ObjectId("538181738d6bd23253654690") },
"movies._id": { "$in": [ 1, 2, 3 ] },
"$and": [
{ "movies": { "$not": { "$size": 1 } } }
]
}},
// Project a copy of the document along with the "set" to match
{ "$project": {
"_id": {
"_id": "$_id",
"movies": "$movies"
},
"movies": 1,
"set": { "$cond": [ 1, [ 1, 2, 3 ], 0 ] }
}},
// Unwind both those arrays
{ "$unwind": "$movies" },
{ "$unwind": "$set" },
// Group back the count where both `_id` values are equal
{ "$group": {
"_id": "$_id",
"movies": {
"$sum": {
"$cond":[
{ "$eq": [ "$movies._id", "$set" ] },
1,
0
]
}
}
}},
// Filter the results to those that actually match
{ "$match": { "movies": { "$gte": 2 } } }
])
विस्तार से
इसमें थोड़ा समय लग सकता है, इसलिए हम प्रत्येक चरण पर एक नज़र डाल सकते हैं और उन्हें तोड़कर देख सकते हैं कि वे क्या कर रहे हैं।
$मिलान :आप संग्रह में प्रत्येक दस्तावेज़ पर काम नहीं करना चाहते हैं, इसलिए यह उन वस्तुओं को हटाने का एक अवसर है जो संभवतः मेल नहीं खाते हैं, भले ही सटीक खोजने के लिए अभी और काम करना बाकी है। वाले। तो स्पष्ट चीजें उसी "उपयोगकर्ता" को बाहर करने के लिए हैं और फिर केवल उन दस्तावेज़ों से मेल खाते हैं जिनमें कम से कम एक ही फिल्म है जो उस "उपयोगकर्ता" के लिए मिली थी।
अगली बात जो समझ में आती है वह यह है कि जब आप n
. से मिलान करना चाहते हैं तो इस पर विचार करें प्रविष्टियाँ तब केवल ऐसे दस्तावेज़ होते हैं जिनमें "मूवीज़" सरणी होती है जो n-1
. से बड़ी होती है संभवतः वास्तव में मैच हो सकते हैं। $and
. का उपयोग यहां अजीब लग रहा है और विशेष रूप से इसकी आवश्यकता नहीं है, लेकिन यदि आवश्यक मिलान 4
थे तो कथन का वह वास्तविक भाग कुछ इस प्रकार दिखाई देगा:
"$and": [
{ "movies": { "$not": { "$size": 1 } } },
{ "movies": { "$not": { "$size": 2 } } },
{ "movies": { "$not": { "$size": 3 } } }
]
तो आप मूल रूप से उन सरणियों को "निष्कासित" करते हैं जो संभवतः n
. के लिए पर्याप्त नहीं हैं मैच। यहां ध्यान दें कि यह $size
क्वेरी फॉर्म में ऑपरेटर $size
एकत्रीकरण ढांचे के लिए। उदाहरण के लिए इसका उपयोग असमानता ऑपरेटर जैसे $gt
. के साथ करने का कोई तरीका नहीं है क्या इसका उद्देश्य विशेष रूप से अनुरोधित "आकार" से मेल खाना है। इसलिए यह क्वेरी फॉर्म उन सभी संभावित आकारों को निर्दिष्ट करने के लिए है जो इससे कम हैं।
$प्रोजेक्ट :इस कथन में कुछ उद्देश्य हैं, जिनमें से कुछ आपके पास मौजूद MongoDB संस्करण के आधार पर भिन्न हैं। सबसे पहले, और वैकल्पिक रूप से, एक दस्तावेज़ की प्रतिलिपि _id
. के अंतर्गत रखी जा रही है value ताकि इन क्षेत्रों को बाकी चरणों द्वारा संशोधित नहीं किया जा सके। यहाँ दूसरा भाग "मूवीज़" सरणी को दस्तावेज़ के शीर्ष पर अगले चरण के लिए एक प्रति के रूप में रख रहा है।
पूर्व 2.6 संस्करणों के लिए प्रस्तुत संस्करण में भी क्या हो रहा है कि _id
का प्रतिनिधित्व करने वाला एक अतिरिक्त सरणी है "फिल्मों" से मेल खाने के लिए मान। $cond
. का उपयोग ऑपरेटर यहां सरणी का "शाब्दिक" प्रतिनिधित्व बनाने का एक तरीका है। काफी अजीब बात है, MongoDB 2.6 एक ऑपरेटर पेश करता है जिसे $literal
. के नाम से जाना जाता है ऐसा करने के लिए हम जिस मज़ेदार तरीके से $cond
. का उपयोग कर रहे हैं उसके बिना ऐसा करने के लिए यहीं।
$खोलें :आगे कुछ भी करने के लिए मूवी ऐरे को खोलना होगा क्योंकि किसी भी स्थिति में मौजूदा _id
को अलग करने का यही एकमात्र तरीका है उन प्रविष्टियों के लिए मान जिन्हें "सेट" के विरुद्ध मिलान करने की आवश्यकता है। तो 2.6 से पहले के संस्करण के लिए आपको मौजूद दोनों सरणियों को "खोलना" चाहिए।
$समूह :MongoDB 2.6 और इससे अधिक के लिए आप केवल एक सरणी में वापस समूहित कर रहे हैं जिसमें केवल _id
है "रेटिंग" वाली फ़िल्मों के मूल्य हटा दिए गए हैं।
2.6 से पहले चूंकि सभी मान "अगल-बगल" (और बहुत सारे दोहराव के साथ) प्रस्तुत किए जाते हैं, आप यह देखने के लिए दो मानों की तुलना कर रहे हैं कि क्या वे समान हैं। जहां वह true
है , यह $cond
. बताता है 1
. का मान लौटाने के लिए ऑपरेटर स्टेटमेंट या 0
जहां शर्त false
है . इसे सीधे $sum
. के माध्यम से वापस भेजा जाता है सरणी में मिलान करने वाले तत्वों की संख्या को आवश्यक "सेट" तक बढ़ाने के लिए।
$प्रोजेक्ट :जहां यह MongoDB 2.6 और इससे अधिक के लिए अलग हिस्सा है, वह यह है कि चूंकि आपने "फिल्मों" _id
की एक सरणी को पीछे धकेल दिया है वे मान जिनका आप उपयोग कर रहे हैं $setIntersection
सीधे उन सरणियों की तुलना करने के लिए। इसके परिणामस्वरूप एक सरणी है जिसमें समान तत्व होते हैं, फिर इसे $size
में लपेटा जाता है ऑपरेटर यह निर्धारित करने के लिए कि मिलान करने वाले सेट में कितने तत्व लौटाए गए थे।
$मिलान :क्या अंतिम चरण यहां लागू किया गया है जो केवल उन दस्तावेजों के मिलान का स्पष्ट चरण करता है जिनके प्रतिच्छेदन तत्वों की संख्या आवश्यक संख्या से अधिक या उसके बराबर थी।
फाइनल
मूल रूप से आप इसे कैसे करते हैं। 2.6 से पहले थोड़ा क्लंकियर है और विस्तार के कारण थोड़ी अधिक मेमोरी की आवश्यकता होगी जो सेट के सभी संभावित मूल्यों द्वारा पाए जाने वाले प्रत्येक सरणी सदस्य को डुप्लिकेट करके किया जाता है, लेकिन यह अभी भी ऐसा करने का एक वैध तरीका है।
आपको बस इतना करना है कि इसे अधिक से अधिक n
. के साथ लागू करें आपकी शर्तों को पूरा करने के लिए मिलान मान, और निश्चित रूप से सुनिश्चित करें कि आपके मूल उपयोगकर्ता मिलान में आवश्यक n
है संभावनाएं। अन्यथा बस इसे n-1
. पर जनरेट करें "मूवी" के "उपयोगकर्ता" सरणी की लंबाई से।