Ähnlich wie bei Ihrer vorherigen Frage
verwenden Sie .bulkWrite()
aber da die Array-Elementauswahl "mehrere Bedingungen" hat, verwenden Sie hier $elemMatch
:
db.collection.bulkWrite([
{ "updateOne": {
"filter": {
"_id": "1",
"option": {
"$elemMatch": { "weight": "40", "size": "40" }
}
},
"update": {
"$set": { "option.$.price": "300" }
}
}},
{ "updateOne": {
"filter": {
"_id": "1",
"option": {
"$not": {
"$elemMatch": { "weight": "40", "size": "40" }
}
}
},
"update": {
"$push": { "option": { "weight": "40", "size": "40", "price": "300" } }
}
}},
{ "updateOne": {
"filter": { "_id": 1 },
"update": {
"$setOnInsert": {
"option": [
{ "weight": "40", "size": "40", "price": "300" }
]
}
},
"upsert": true
}}
])
Die Operationen sind also:
-
Testen Sie, ob die Array-Element-Übereinstimmungsbedingungen in
$elemMatch
vorhanden ist und dann$set
der übereinstimmende Wert. -
Testen Sie, dass das Array-Element
$not
ist in Verneinung vorhanden. Alternativ können Sie$ne
verwenden auf jeder Eigenschaft, aber das Negieren der Bedingung, in der beide übereinstimmen, ist etwas sauberer."$elemMatch": { "weight": { "$ne": "40" }, "size": { "$ne": "40" } }
Auf jeden Fall
$push
das neue Array-Element, wenn man nicht Übereinstimmung mit den angegebenen Kriterien gefunden. -
Versuchen Sie ein "Upsert" nur dort, wo das primäre Dokument
_id
ist nicht gefunden wird, und verwenden Sie$setOnInsert
so dass diese Operation nichts bewirkt, wenn das Dokument gefunden wird.
Wie zuvor wird nur einer von ihnen tatsächlich etwas schreiben, obwohl der gesamte Stapel an den Server gesendet wird.