Ne, na tohle opravdu není lepší řešení, tak snad s vysvětlením.
Předpokládejme, že máte na místě dokument, který má strukturu, jakou ukazujete:
{
"name": "foo",
"bars": [{
"name": "qux",
"somefield": 1
}]
}
Pokud provedete aktualizaci takto
db.foo.update(
{ "name": "foo", "bars.name": "qux" },
{ "$set": { "bars.$.somefield": 2 } },
{ "upsert": true }
)
Pak je vše v pořádku, protože byl nalezen odpovídající dokument. Ale pokud změníte hodnotu "bars.name":
db.foo.update(
{ "name": "foo", "bars.name": "xyz" },
{ "$set": { "bars.$.somefield": 2 } },
{ "upsert": true }
)
Pak dojde k selhání. Jediná věc, která se zde skutečně změnila, je to, že v MongoDB 2.6 a vyšší je chyba o něco stručnější:
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"
}
})
To je v některých ohledech lepší, ale stejně se ve skutečnosti nechcete "upsertovat". Co chcete udělat, je přidat prvek do pole, kde "name" aktuálně neexistuje.
Takže to, co opravdu chcete, je „výsledek“ pokusu o aktualizaci bez příznaku „upsert“, abyste zjistili, zda byly ovlivněny nějaké dokumenty:
db.foo.update(
{ "name": "foo", "bars.name": "xyz" },
{ "$set": { "bars.$.somefield": 2 } }
)
Výtěžnost v reakci:
WriteResult({ "nMatched" : 0, "nUpserted" : 0, "nModified" : 0 })
Takže když jsou upravené dokumenty 0
pak víte, že chcete vydat následující aktualizaci:
db.foo.update(
{ "name": "foo" },
{ "$push": { "bars": {
"name": "xyz",
"somefield": 2
}}
)
Opravdu neexistuje žádný jiný způsob, jak dělat přesně to, co chcete. Protože přidání do pole není striktně "set" typem operace, nemůžete použít $addToSet
v kombinaci s funkcí "hromadné aktualizace", takže můžete "kaskádovat" své požadavky na aktualizaci.
V tomto případě se zdá, že musíte zkontrolovat výsledek nebo jinak přijmout čtení celého dokumentu a zkontrolovat, zda se má aktualizovat nebo vložit nový prvek pole do kódu.