Du vill ha .bulkWrite()
för detta. Detta är faktiskt inte en enda operation, så du vill skicka flera operationer i en enda begäran. Försök att skriva uppdateringen med $set
där data finns eller $push
den nya data där den inte finns:
db.collection.bulkWrite([
{ "updateOne": {
"filter": { "_id": "1", "option.weight": "10" },
"update": {
"$set": { "option.$.price": "30" }
}
}},
{ "updateOne": {
"filter": { "_id": "1", "option.weight": { "$ne": "10" } },
"update": {
"$push": { "option": { "weight": "10", "price": "30" } }
}
}}
])
Det positiva fallet är helt enkelt värdet och $ne
"negerer" jämställdhetsmatchningen, vilket betyder att föremålet inte existerar. Naturligtvis positionella $
operatör
används med $set
där det gör
Med tanke på data kommer endast en av operationerna faktiskt att matcha och tillämpas som en uppdatering trots att två operationer skickas i "batchen".
Om du vill ha "upserts" för hela dokumentet också, måste du lägga till en annan operation i slutet av det. Observera att du inte kan använda "upsert" som ett alternativ på något av de andra påståendena, särskilt $ne
eftersom det skulle skapa ett nytt dokument där arrayobjektet inte finns, inte bara _id
:
db.collection.bulkWrite([
{ "updateOne": {
"filter": { "_id": "1", "option.weight": "10" },
"update": {
"$set": { "option.$.price": "30" }
}
}},
{ "updateOne": {
"filter": { "_id": "1", "option.weight": { "$ne": "10" } },
"update": {
"$push": { "option": { "weight": "10", "price": "30" } }
}
}},
{ "updateOne": {
"filter": { "_id": 1 },
"update": {
"$setOnInsert": {
"option": [
{ "weight": "10", "price": "30" }
]
}
},
"upsert": true
}}
])
$setOnInsert
är den viktigaste hjälpen här förutom att den sista operationen är den enda som är markerad som "upsert"
. Den kombinationen säkerställer att där det primära "dokumentet" hittas händer ingenting, men när det inte hittas läggs det nya arrayobjektet till.
Som en sidoanteckning skulle jag starkt rekommendera att lagra numeriska värden faktiskt som numeriska snarare än strängar. Det sparar inte bara utrymme i de flesta fall utan det är också mycket mer användbart på det sättet.