Nein, es gibt keine bessere Lösung dafür, also vielleicht mit einer Erklärung.
Angenommen, Sie haben ein Dokument mit der von Ihnen gezeigten Struktur:
{
"name": "foo",
"bars": [{
"name": "qux",
"somefield": 1
}]
}
Wenn Sie ein solches Update durchführen
db.foo.update(
{ "name": "foo", "bars.name": "qux" },
{ "$set": { "bars.$.somefield": 2 } },
{ "upsert": true }
)
Dann ist alles in Ordnung, weil ein passendes Dokument gefunden wurde. Aber wenn Sie den Wert von "bars.name" ändern:
db.foo.update(
{ "name": "foo", "bars.name": "xyz" },
{ "$set": { "bars.$.somefield": 2 } },
{ "upsert": true }
)
Dann bekommst du einen Fehler. Das einzige, was sich hier wirklich geändert hat, ist, dass in MongoDB 2.6 und höher der Fehler etwas prägnanter ist:
WriteResult({
"nMatched" : 0,
"nUpserted" : 0,
"nModified" : 0,
"writeError" : {
"code" : 16836,
"errmsg" : "The positional operator did not find the match needed from the query. Unexpanded update: bars.$.somefield"
}
})
Das ist in gewisser Weise besser, aber Sie wollen sowieso nicht "aufregen". Sie möchten das Element dem Array hinzufügen, in dem der "Name" derzeit nicht vorhanden ist.
Was Sie also wirklich wollen, ist das "Ergebnis" des Aktualisierungsversuchs ohne das "Upsert"-Flag, um zu sehen, ob irgendwelche Dokumente betroffen waren:
db.foo.update(
{ "name": "foo", "bars.name": "xyz" },
{ "$set": { "bars.$.somefield": 2 } }
)
Nachgeben als Antwort:
WriteResult({ "nMatched" : 0, "nUpserted" : 0, "nModified" : 0 })
Wenn also die geänderten Dokumente 0
sind dann wissen Sie, dass Sie das folgende Update herausgeben möchten:
db.foo.update(
{ "name": "foo" },
{ "$push": { "bars": {
"name": "xyz",
"somefield": 2
}}
)
Es gibt wirklich keine andere Möglichkeit, genau das zu tun, was Sie wollen. Da die Hinzufügungen zum Array streng genommen keine "Set"-Operationen sind, können Sie $addToSet
nicht verwenden kombiniert mit der dortigen "Bulk-Update"-Funktionalität, so dass Sie Ihre Update-Anfragen "kaskadieren" können.
In diesem Fall scheint es, als müssten Sie das Ergebnis überprüfen oder das gesamte Dokument lesen und prüfen, ob ein neues Array-Element im Code aktualisiert oder eingefügt werden soll.