मुख्य समस्या यह है कि findOneAndUpdate
ठीक वही करता है जो उसके नाम का तात्पर्य है। यह एक find
. को क्रियान्वित करता है प्रदान किए गए फ़िल्टर का उपयोग करते हुए, और यदि कोई मेल मिलता है, तो पहले मिलान वाले दस्तावेज़ में अपडेट लागू करता है।
यदि संग्रह में केवल यह दस्तावेज़ है:
[
{
"_id": "5e90ae0e0ed9974174e92826",
"payments": [
{
"year_month": "2020_02",
"status": false
}
]
}
]
प्रारंभिक खोज भाग अनिवार्य रूप से
. है.find({
_id: '5e90ae0e0ed9974174e92826',
payments: { $elemMatch: { year_month: '2020_03' }}
})
यह कुछ भी मेल नहीं खाता है, और चूंकि अप्सर्ट सत्य पर सेट है, ठीकवनएंडअपडेट एक नया दस्तावेज़ बनाने का प्रयास करता है। यहां तक कि अगर यह एक बेजोड़ स्थितीय ऑपरेटर से एक सरणी बनाने में सक्षम था, तो वह जिस दस्तावेज़ को जोड़ने का प्रयास कर रहा होगा वह होगा:
{
"_id": "5e90ae0e0ed9974174e92826",
"payments": [
{
"year_month": "2020_03",
"status": false
}
]
}
यह सही नहीं है, और डुप्लीकेट _id
. के कारण सम्मिलित करने में विफल रहेगा वैसे भी मूल्य।
यदि आप MongoDB 4.2 का उपयोग कर रहे हैं, तो आप findAndUpdate
के दूसरे तर्क के रूप में एकत्रीकरण पाइपलाइन का उपयोग कर सकते हैं जिस तत्व में आप रुचि रखते हैं उसके लिए सरणी की जाँच करने के लिए और यदि वह गायब है तो उसे जोड़ें।
एक नहीं बहुत सुंदर विधि नीचे है। FindOneAndUpdate _id से मेल खाएगा, और पाइपलाइन निम्न कार्य करेगी:
- जांचें कि क्या सरणी में कोई तत्व वांछित वर्ष_माह से मेल खाता है
- यदि ऐसा है, तो उस तत्व में स्थिति फ़ील्ड को अपडेट करने के लिए सरणी को कम करें
- यदि नहीं, तो एक नया तत्व जोड़ें
- परिणाम को वापस payments
पर असाइन करें
.findOneAndUpdate(
{ "_id": "5e90ae0e0ed9974174e92826" },
[{$set: {
payments: {$cond:[
{$gt:[
{$size:
{$filter:{
input:"$payments",
cond:{$eq:["$$this.year_month","2020_03"]}
}}},
1
]},
{$reduce:{
input:"$payments",
initialValue:[],
in:{$concatArrays:[
"$$value",
[{$cond:[
{$eq:["$$this.j",3]},
{$mergeObjects:["$$this",{status:true}]},
"$$this"
]}]
]}
}},
{$concatArrays:[
"$payments",
[{year_month:"2020_03", status:true}]
]}
]}
}}]
)