Der Prozess hier ist wirklich ganz einfach, er variiert nur darin, wo Sie die Elemente im Array "finden oder erstellen" möchten.
Angenommen, die Elemente für jeden Schlüssel sind bereits vorhanden, dann besteht der einfache Fall darin, das Element abzufragen und mit dem Index zu aktualisieren, der über positional $
Betreiber:
db.collection.update(
{
"_id": docId,
"attrs": { "$elemMatch": { "key": "A1", "type": "T1" } }
}
{ "$set": { "attrs.$.value": "20" }
)
Dadurch wird nur das übereinstimmende Element geändert, ohne andere zu beeinflussen.
Im zweiten Fall, in dem "finden oder erstellen" erforderlich ist und der bestimmte Schlüssel möglicherweise nicht existiert, verwenden Sie "zwei" Aktualisierungsanweisungen. Aber die Bulk Operations API ermöglicht Ihnen, dies in einer einzigen Anfrage an den Server mit einer einzigen Antwort zu tun:
var bulk = db.collection.initializeOrderedBulkOp();
// Try to update where exists
bulk.find({
"_id": docId,
"attrs": { "$elemMatch": { "key": "A1", "type": "T2" } }
}).updateOne({
"$set": { "attrs.$.value": "30" }
});
// Try to add where does noes not exist
bulk.find({
"_id": docId,
"attrs": { "$not": { "$elemMatch": { "key": "A1", "type": "T2" } } }
}).updateOne({
"$push": { "attrs": { "key": "A1", "type": "T2", "value": "30" } }
});
bulk.execute();
Die grundlegende Logik besteht darin, dass zuerst der Aktualisierungsversuch unternommen wird, um ein Element mit den erforderlichen Werten abzugleichen, genau wie zuvor. Die andere Bedingung testet, wo das Element überhaupt nicht gefunden wird, indem die Übereinstimmungslogik mit $not
.
Falls das Array-Element nicht gefunden wurde, kann ein neues über $push
.
Ich sollte wirklich hinzufügen, dass es immer eine gute Idee ist, das "Dokument", das Sie aktualisieren möchten, mit einer eindeutigen Kennung wie der _id
abzugleichen, da wir hier speziell nach negativen Übereinstimmungen suchen Schlüssel. Auch wenn dies mit "Multi"-Updates möglich ist, müssen Sie vorsichtig sein, was Sie tun.
Wenn also der Prozess „Suchen oder Erstellen“ ausgeführt wird, wird das Element, das nicht übereinstimmt, korrekt zum Array hinzugefügt, ohne andere Elemente zu stören, auch die vorherige Aktualisierung für eine erwartete Übereinstimmung wird auf die gleiche Weise angewendet:
{
"_id" : ObjectId("55b570f339db998cde23369d"),
"attrs" : [
{
"key" : "A1",
"type" : "T1",
"value" : "20"
},
{
"key" : "A2",
"type" : "T2",
"value" : "14"
},
{
"key" : "A1",
"type" : "T2",
"value" : "30"
}
]
}
Dies ist ein einfaches Muster, und natürlich beseitigen die Bulk-Vorgänge hier jeglichen Overhead, indem sie mehrere Anfragen an und von dem Server senden und empfangen. All dies funktioniert problemlos, ohne andere Elemente zu beeinträchtigen, die möglicherweise vorhanden sind oder nicht.
Abgesehen davon gibt es die zusätzlichen Vorteile, die Daten für eine einfache Abfrage und Analyse in einem Array zu halten, wie es von den Standardoperatoren unterstützt wird, ohne dass auf die JavaScript-Serververarbeitung zurückgegriffen werden muss, um die Elemente zu durchlaufen.