यह वास्तव में उतना सरल नहीं है जितना आप सोच सकते हैं, और वास्तव में यह दिलचस्प है कि आपने इसके विश्लेषण को तीन भागों में विभाजित किया है। क्योंकि, अनुमान लगाओ क्या? ठीक यही आपको होना चाहिए करना। आइए चरणों पर विचार करें:
<एच3>1. यदि कोई दस्तावेज़ मौजूद नहीं है तो डालेंdb.collection.update(
{
"clientId":"123456"
},
{
"$setOnInsert": {
"clientId": "123456",
"devices": [{
"deviceId": "321",
"deviceType" : "kindle",
"notification" : false
}]
}
},
{ "upsert": true }
)
तो आप क्या करना चाहते हैं सम्मिलित करें एक नया दस्तावेज़ जहाँ "clientId" वर्तमान में मौजूद नहीं है। यह संभव अद्वितीय कुंजी संघर्षों से बचने के लिए "अप्सर्ट" के रूप में किया जा सकता है और यहां तक कि जहां कोई "अद्वितीय" बाधा नहीं है, तो इसकी "अप्सर्ट" प्रकृति सुनिश्चित करती है कि आप केवल "नया" दस्तावेज़ बनाते हैं जब यह नहीं मिला। इसके अलावा $setOnInsert
. है यहाँ क्योंकि आप नहीं उस दस्तावेज़ के लिए कुछ भी करना चाहते हैं जो इस बिंदु पर "मिला" है।
यहां ध्यान दें कि नहीं . है सरणी में तत्व से मिलान करने का प्रयास करें। ऐसा इसलिए है क्योंकि आप संभवतः एक नया दस्तावेज़ "बनाना" नहीं चाहते हैं, क्योंकि किसी मौजूदा में "वह" सरणी तत्व नहीं है। जो हमें अगले चरण पर लाता है।
<एच3>2. दस्तावेज़ की सामग्री को अपडेट करें जहां यह मौजूद हैdb.collection.update(
{
"clientId":"123456",
"devices": { "$elemMatch": { "deviceId" : "321" } }
},
{
"$set": {
"devices.$.deviceType" : "kindle",
"devices.$.notification" : false
}
}
)
अब यहां आप वास्तव में कोशिश करना चाहते हैं और "clientId" के लिए दस्तावेज़ को "मिलान" करना चाहते हैं जो करता है सरणी में एक तत्व है जो "डिवाइस आईडी" से मेल खाता है जिसे आप ढूंढ रहे हैं। तो मिलान करने के लिए एक शर्त निर्दिष्ट करके, आपको स्थितीय $
. का उपयोग मिलता है फ़ील्ड को "मिलान" स्थिति में सेट करने के लिए ऑपरेटर।
ऊपर के रूप में, यह या तो एक . से मेल खाने वाला था चीज़ या कुछ भी नहीं तो या तो अद्यतन किया गया था या यह नहीं था। ताकि यहां कैस्केड के हमारे अंतिम भाग की ओर बढ़ें:
<एच3>3. सरणी तत्व जोड़ें जहां यह मौजूद नहीं हैdb.collection.update(
{
"clientId":"123456"
},
{
"$addToset": { "devices": {
"deviceId" : "321",
"deviceType" : "kindle",
"notification" : false
}}
}
)
तो यह महत्वपूर्ण है अंतिम चरण। इसका कारण यह है कि यदि पूर्ववर्ती में से कोई एक ऑपरेशन किया मौजूदा दस्तावेज़ को "बनाएं" या "अपडेट" करें, फिर $addToSet
. का उपयोग करें यहाँ सुनिश्चित बनाता है आप उसी "डिवाइस आईडी" के साथ सरणी में किसी अन्य दस्तावेज़ को "धक्का" नहीं दे रहे हैं लेकिन अन्य अलग-अलग मान हैं। अगर एक उन चरणों में से काम किया, तो यह उस तत्व के सभी मूल्यों को पहले से मौजूद देखेगा, और फिर दूसरा नहीं जोड़ेगा।
यदि आप इसे किसी भिन्न क्रम में करने का प्रयास करते हैं, तो आपके द्वारा प्रस्तुत किए जाने की स्थिति में आपके पास दो . होगा एक ही "डिवाइस आईडी" के साथ सरणी में दस्तावेज़, लेकिन "डिवाइस टाइप" और "अधिसूचना" के लिए अलग-अलग मान। इसलिए यह सबसे आखिर में आता है।
निष्कर्ष
इसलिए दुर्भाग्य से, इन्हें एक . के रूप में संयोजित करने का कोई आसान तरीका नहीं है कार्यवाही। ऑपरेटर बस मौजूद नहीं हैं ताकि यह एक ही कथन में किया जा सके और इसलिए आपको जरूरी प्रदर्शन तीन आप जो चाहते हैं उसे करने के लिए संचालन अद्यतन करें। जैसा कि कहा गया है, आदेश उन अपडेट के लिए आवेदन की संख्या महत्वपूर्ण है ताकि आपको मनचाहा परिणाम मिले।
हालांकि यह अभी तक वर्तमान "उत्पादन" रिलीज़ में मौजूद नहीं है, आगामी रिलीज़ (2.6 और ऊपर की ओर लेखन के रूप में) के पास इन अनुरोधों को अद्यतन करने के लिए एक नए सिंटैक्स के साथ "बैच" करने का एक तरीका है:
db.runCommand(
"update": "collection",
"updates": [
{
"q": { "clientId":"123456" },
"u": {
"$setOnInsert": {
"clientId": "123456",
"devices": [{
"deviceId": "321",
"deviceType" : "kindle",
"notification" : false
}]
},
"upsert": true
},
{
"q": {
"clientId":"123456",
"devices": { "$elemMatch": { "deviceId" : "321" } }
},
"u": {
"$set": {
"devices.$.deviceType" : "kindle",
"devices.$.notification" : false
}
}
},
{
"q": { "clientId":"123456" },
"u": {
"$addToset": { "devices": {
"deviceId" : "321",
"deviceType" : "kindle",
"notification" : false
}}
}
}
]
)
तो जबकि वह अभी भी . है अनिवार्य रूप से तीन ऑपरेशन, कम से कम आप उन्हें वायर पर send भेज सकते हैं सिर्फ एक बार