Nej, der er ikke rigtig en bedre løsning på dette, så måske med en forklaring.
Antag, at du har et dokument på plads, der har den struktur, du viser:
{
"name": "foo",
"bars": [{
"name": "qux",
"somefield": 1
}]
}
Hvis du laver en opdatering som denne
db.foo.update(
{ "name": "foo", "bars.name": "qux" },
{ "$set": { "bars.$.somefield": 2 } },
{ "upsert": true }
)
Så er alt i orden, fordi der blev fundet et matchende dokument. Men hvis du ændrer værdien af "bars.name":
db.foo.update(
{ "name": "foo", "bars.name": "xyz" },
{ "$set": { "bars.$.somefield": 2 } },
{ "upsert": true }
)
Så får du en fiasko. Det eneste, der virkelig har ændret sig her, er, at i MongoDB 2.6 og nyere er fejlen lidt mere kortfattet:
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"
}
})
Det er bedre på nogle måder, men du har virkelig ikke lyst til at "oprøre" alligevel. Det, du vil gøre, er at tilføje elementet til arrayet, hvor "navnet" ikke eksisterer i øjeblikket.
Så det, du virkelig ønsker, er "resultatet" fra opdateringsforsøget uden "upsert"-flaget for at se, om nogen dokumenter blev påvirket:
db.foo.update(
{ "name": "foo", "bars.name": "xyz" },
{ "$set": { "bars.$.somefield": 2 } }
)
Giver efter som svar:
WriteResult({ "nMatched" : 0, "nUpserted" : 0, "nModified" : 0 })
Så når de ændrede dokumenter er 0
så ved du, at du vil udstede følgende opdatering:
db.foo.update(
{ "name": "foo" },
{ "$push": { "bars": {
"name": "xyz",
"somefield": 2
}}
)
Der er virkelig ingen anden måde at gøre præcis, hvad du vil. Da tilføjelserne til arrayet ikke udelukkende er en "set"-operation, kan du ikke bruge $addToSet
kombineret med "bulk update"-funktionaliteten der, så du kan "cascade" dine opdateringsanmodninger.
I dette tilfælde ser det ud til, at du skal tjekke resultatet eller på anden måde acceptere at læse hele dokumentet og kontrollere, om du vil opdatere eller indsætte et nyt array-element i kode.