Mit einem einzigen atomaren Update ist das leider nicht möglich, Sie müssten ein paar Update-Operationen durchführen, die beide Bedingungen erfüllen.
Brechen Sie die Aktualisierungslogik in zwei unterschiedliche Aktualisierungsvorgänge auf, der erste würde die Verwendung von positionelles $
Betreiber
um das Element im history
zu identifizieren gewünschten Array und den $set
um die vorhandenen Felder zu aktualisieren. Diese Operation folgt der Logik Felder aktualisieren, WENN Name UND Organisation übereinstimmen
Nun möchten Sie den findAndModify()
-Methode für diesen Vorgang, da sie das aktualisierte Dokument zurückgeben kann. Standardmäßig enthält das zurückgegebene Dokument nicht die beim Update vorgenommenen Änderungen.
Bewaffnet mit diesem Arsenal können Sie dann Ihre zweite Logik in der nächsten Operation untersuchen, d. h. aktualisieren, WENN diese Kombination aus "history.name" und "history.organisation" nicht im Array vorhanden ist . Bei diesem zweiten Aktualisierungsvorgang müssten Sie dann den $push
Operator zum Hinzufügen der Elemente.
Das folgende Beispiel demonstriert das obige Konzept. Zunächst wird davon ausgegangen, dass Sie den Abfrageteil und das zu aktualisierende Dokument als separate Objekte haben.
Wenn wir beispielsweise Dokumente haben, die mit dem vorhandenen Verlaufs-Array übereinstimmen, wird nur ein einziger Aktualisierungsvorgang durchgeführt, aber wenn die Dokumente nicht übereinstimmen, wird der findAndModify()
-Methode null zurückgibt, verwenden Sie diese Logik in Ihrem zweiten Aktualisierungsvorgang, um das Dokument in das Array zu verschieben:
var doc = {
"name": "Test123",
"organisation": "Rat"
}, // document to update. Note: the doc here matches the existing array
query = { "email": "[email protected]" }; // query document
query["history.name"] = doc.name; // create the update query
query["history.organisation"] = doc.organisation;
var update = db.users.findAndModify({
"query": query,
"update": {
"$set": {
"history.$.name": doc.name,
"history.$.organisation": doc.organisation
}
}
}); // return the document modified, if there's no matched document update = null
if (!update) {
db.users.update(
{ "email": query.email },
{ "$push": { "history": doc } }
);
}
Nach dieser Operation für übereinstimmende Dokumente ergibt die Abfrage der Sammlung dasselbe
db.users.find({ "email": "[email protected]" });
Ausgabe:
{
"_id" : ObjectId("575fe85bfe98c1fba0a6e535"),
"email" : "[email protected]",
"__v" : 0,
"history" : [
{
"name" : "Test123",
"organisation" : "Rat",
"field" : 4,
"another" : 3
}
]
}
Betrachten Sie nun Dokumente, die nicht übereinstimmen:
var doc = {
"name": "foo",
"organisation": "bar"
}, // document to update. Note: the doc here does not matches the current array
query = { "email": "[email protected]" }; // query document
query["history.name"] = doc.name; // create the update query
query["history.organisation"] = doc.organisation;
var update = db.users.findAndModify({
"query": query,
"update": {
"$set": {
"history.$.name": doc.name,
"history.$.organisation": doc.organisation
}
}
}); // return the document modified, if there's no matched document update = null
if (!update) {
db.users.update(
{ "email": query.email },
{ "$push": { "history": doc } }
);
}
Diese Sammlung wird nach diesem Dokument abgefragt
db.users.find({ "email": "[email protected]" });
würde nachgeben
Ausgabe:
{
"_id" : ObjectId("575fe85bfe98c1fba0a6e535"),
"email" : "[email protected]",
"__v" : 0,
"history" : [
{
"name" : "Test123",
"organisation" : "Rat",
"field" : 4,
"another" : 3
},
{
"name" : "foo",
"organisation" : "bar"
}
]
}