आप यहां जो करने की कोशिश कर रहे हैं वह केवल एक सरणी में एक नया आइटम जोड़ना है जहां आइटम मौजूद नहीं है और जहां यह मौजूद नहीं है वहां एक नया दस्तावेज़ भी बनाएं। आप $addToSet
. चुनें क्योंकि आप चाहते हैं कि आइटम अद्वितीय हों, लेकिन वास्तव में आप वास्तव में उन्हें केवल "a" द्वारा अद्वितीय बनाना चाहते हैं।
तो $addToset
ऐसा नहीं करेंगे, और आपको मौजूद तत्व को "परीक्षण" करने की आवश्यकता है। लेकिन यहां असली समस्या यह है कि ऐसा करना और एक ही समय में "अपरर्ट" करना दोनों संभव नहीं है। तर्क काम नहीं कर सकता क्योंकि एक नया दस्तावेज़ तब बनाया जाएगा जब सरणी तत्व नहीं मिला था, बजाय इसके कि आप जैसे सरणी तत्व को जोड़ना चाहते हैं।
$addToSet
. के रूप में डिज़ाइन द्वारा वर्तमान संचालन त्रुटियां किसी सरणी को "बनाने" के लिए उपयोग नहीं किया जा सकता है, लेकिन केवल मौजूदा सरणी में सदस्यों को "जोड़ने" के लिए उपयोग किया जा सकता है। लेकिन जैसा कि पहले ही कहा जा चुका है, आपको तर्क हासिल करने में अन्य समस्याएं हैं।
यहां आपको जो चाहिए वह अद्यतन संचालन का एक क्रम है जो प्रत्येक अपनी अपेक्षित कार्रवाई करने के लिए "कोशिश" करता है। यह केवल कई कथनों के साथ किया जा सकता है:
// attempt "upsert" where document does not exist
// do not alter the document if this is an update
db.test.update(
{ "name": "abc" },
{ "$setOnInsert": { "config": [{ "a": 1, "b": 2 }] }},
{ "upsert": true }
)
// $push the element where "a": 1 does not exist
db.test.update(
{ "name": "abc", "config.a": { "$ne": 1 } },
{ "$push": { "config": { "a": 1, "b": 2 } }}
)
// $set the element where "a": 1 does exist
db.test.update(
{ "name": "abc", "config.a": 1 },
{ "$set": { "config.$.b": 2 } }
)
पहले पुनरावृत्ति पर पहला कथन दस्तावेज़ को "अपरर्ट" करेगा और वस्तुओं के साथ सरणी बनाएगा। दूसरा कथन दस्तावेज़ से मेल नहीं खाएगा क्योंकि "ए" तत्व में वह मान है जो निर्दिष्ट किया गया था। तीसरा स्टेटमेंट दस्तावेज़ से मेल खाएगा लेकिन यह इसे राइट ऑपरेशन में नहीं बदलेगा क्योंकि मान नहीं बदले हैं।
अगर आप अब इनपुट को "b": 3
. में बदलते हैं आपको अलग-अलग प्रतिक्रियाएं मिलती हैं लेकिन वांछित परिणाम:
db.test.update(
{ "name": "abc" },
{ "$setOnInsert": { "config": [{ "a": 1, "b": 3 }] }},
{ "upsert": true }
)
db.test.update(
{ "name": "abc", "config.a": { "$ne": 1 } },
{ "$push": { "config": { "a": 1, "b": 3 } }}
)
db.test.update(
{ "name": "abc", "config.a": 1 },
{ "$set": { "config.$.b": 3 } }
)
तो अब पहला स्टेटमेंट "name": "abc"
. के साथ एक डॉक्यूमेंट से मेल खाता है लेकिन कुछ भी नहीं करता है क्योंकि केवल वैध संचालन "सम्मिलित करें" पर हैं। दूसरा कथन मेल नहीं खाता क्योंकि "ए" शर्त से मेल खाता है। तीसरा स्टेटमेंट "ए" के मान से मेल खाता है और मिलान किए गए तत्व में "बी" को वांछित मान में बदल देता है।
इसके बाद "ए" को दूसरे मान में बदलना जो सरणी में मौजूद नहीं है, 1 और 3 दोनों को कुछ भी नहीं करने की अनुमति देता है लेकिन दूसरा कथन सामग्री को उनकी "ए" कुंजी द्वारा अद्वितीय रखते हुए सरणी में एक और सदस्य जोड़ता है।
साथ ही मौजूदा डेटा में कोई बदलाव नहीं किए जाने के साथ एक स्टेटमेंट सबमिट करने से निश्चित रूप से एक प्रतिक्रिया मिलेगी जो कहती है कि सभी खातों में कुछ भी नहीं बदला है।
इस तरह आप अपना ऑपरेशन करते हैं। आप इसे "आदेशित" थोक के साथ कर सकते हैं संचालन ताकि संशोधित या बनाए गए वैध प्रतिक्रिया के साथ सर्वर से केवल एक ही अनुरोध और प्रतिक्रिया हो।