Não, não há realmente uma solução melhor para isso, então talvez com uma explicação.
Suponha que você tenha um documento em vigor que tenha a estrutura mostrada:
{
"name": "foo",
"bars": [{
"name": "qux",
"somefield": 1
}]
}
Se você fizer uma atualização como esta
db.foo.update(
{ "name": "foo", "bars.name": "qux" },
{ "$set": { "bars.$.somefield": 2 } },
{ "upsert": true }
)
Então está tudo bem porque o documento correspondente foi encontrado. Mas se você alterar o valor de "bars.name":
db.foo.update(
{ "name": "foo", "bars.name": "xyz" },
{ "$set": { "bars.$.somefield": 2 } },
{ "upsert": true }
)
Então você vai ter um fracasso. A única coisa que realmente mudou aqui é que no MongoDB 2.6 e acima o erro é um pouco mais sucinto:
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"
}
})
Isso é melhor em alguns aspectos, mas você realmente não quer "upsert" de qualquer maneira. O que você quer fazer é adicionar o elemento à matriz onde o "nome" não existe atualmente.
Então, o que você realmente quer é o "resultado" da tentativa de atualização sem o sinalizador "upsert" para ver se algum documento foi afetado:
db.foo.update(
{ "name": "foo", "bars.name": "xyz" },
{ "$set": { "bars.$.somefield": 2 } }
)
Cedendo em resposta:
WriteResult({ "nMatched" : 0, "nUpserted" : 0, "nModified" : 0 })
Então, quando os documentos modificados são
0
então você sabe que deseja emitir a seguinte atualização:db.foo.update(
{ "name": "foo" },
{ "$push": { "bars": {
"name": "xyz",
"somefield": 2
}}
)
Realmente não há outra maneira de fazer exatamente o que você quer. Como as adições ao array não são estritamente um tipo de operação "conjunto", você não pode usar
$addToSet
combinado com a funcionalidade de "atualização em massa" lá, para que você possa "desencadear" suas solicitações de atualização. Nesse caso, parece que você precisa verificar o resultado ou aceitar ler todo o documento e verificar se deseja atualizar ou inserir um novo elemento de matriz no código.