Не, всъщност няма по-добро решение за това, така че може би с обяснение.
Да предположим, че имате документ, който има структурата, както показвате:
{
"name": "foo",
"bars": [{
"name": "qux",
"somefield": 1
}]
}
Ако направите такава актуализация
db.foo.update(
{ "name": "foo", "bars.name": "qux" },
{ "$set": { "bars.$.somefield": 2 } },
{ "upsert": true }
)
Тогава всичко е наред, защото е намерен съвпадащ документ. Но ако промените стойността на "bars.name":
db.foo.update(
{ "name": "foo", "bars.name": "xyz" },
{ "$set": { "bars.$.somefield": 2 } },
{ "upsert": true }
)
Тогава ще получите провал. Единственото нещо, което наистина се промени тук, е, че в MongoDB 2.6 и по-нова версия грешката е малко по-сбита:
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"
}
})
Това е по-добре в някои отношения, но така или иначе наистина не искате да се "разстройвате". Това, което искате да направите, е да добавите елемента към масива, където "name" в момента не съществува.
Така че това, което наистина искате, е „резултатът“ от опита за актуализиране без флага „upsert“, за да видите дали някакви документи са били засегнати:
db.foo.update(
{ "name": "foo", "bars.name": "xyz" },
{ "$set": { "bars.$.somefield": 2 } }
)
Отстъпка в отговор:
WriteResult({ "nMatched" : 0, "nUpserted" : 0, "nModified" : 0 })
Така че, когато модифицираните документи са 0
тогава знаете, че искате да издадете следната актуализация:
db.foo.update(
{ "name": "foo" },
{ "$push": { "bars": {
"name": "xyz",
"somefield": 2
}}
)
Наистина няма друг начин да направите точно това, което искате. Тъй като допълненията към масива не са строго "набор" тип операция, не можете да използвате $addToSet
в съчетание с функционалността за „групова актуализация“ там, така че да можете да „каскадирате“ заявките си за актуализиране.
В този случай изглежда, че трябва да проверите резултата или да приемете по друг начин да прочетете целия документ и да проверите дали да актуализирате или вмъкнете нов елемент от масива в кода.