Sie möchten .bulkWrite()
dafür. Dies ist eigentlich kein einzelner Vorgang, daher möchten Sie mehrere Vorgänge in einer einzigen Anforderung übermitteln. Versuchen Sie im Wesentlichen, das Update mit $set
zu schreiben
wo Daten existieren oder $push
die neuen Daten, wo sie nicht existieren:
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" } }
}
}}
])
Der positive Fall ist einfach der Wert und der $ne
"negiert" die Gleichheitsübereinstimmung, was bedeutet, dass das Element nicht existiert. Natürlich der positionsbezogene $
Betreiber
wird mit $set
verwendet
wo es tut
Angesichts der Daten wird nur eine der Operationen tatsächlich übereinstimmen und als Aktualisierung gelten, obwohl zwei Operationen im "Batch" gesendet werden.
Wenn Sie auch "Upserts" für das gesamte Dokument wünschen, müssen Sie am Ende eine weitere Operation hinzufügen. Beachten Sie, dass Sie "upsert" nicht als Option auf eine der anderen Anweisungen anwenden können, insbesondere auf $ne
denn das würde ein neues Dokument erstellen, in dem das Array-Element nicht existiert, nicht nur die _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
}}
])
Der $setOnInsert
ist hier die Haupthilfe, abgesehen davon, dass die letzte Operation die einzige ist, die als "upsert"
gekennzeichnet ist . Diese Kombination stellt sicher, dass dort, wo das primäre "Dokument" gefunden wird, eigentlich nichts passiert, aber wenn es nicht gefunden wird, wird das neue Array-Element hinzugefügt.
Als Randnotiz würde ich dringend empfehlen, numerische Werte tatsächlich als numerische und nicht als Zeichenfolgen zu speichern. Das spart in den meisten Fällen nicht nur Platz, sondern ist auf diese Weise auch viel nützlicher.