EDITAR
O detalhe que faltava na pergunta era que o campo obrigatório para atualização estava na verdade em um subdocumento . Isso muda consideravelmente a resposta:
Esta é uma restrição do que você pode possivelmente fazer com a atualização de elementos da matriz. E isso está claramente explicado na documentação . Principalmente neste parágrafo:
O negócio é o seguinte. Tentando atualizar todos dos elementos da matriz em uma única instrução como esta não trabalhar. Para fazer isso, você deve fazer o seguinte.
db.warehouses.find({ "items.qty": { "$gt": 0 } }).forEach(function(doc) {
doc.items.forEach(function(item) {
item.qty = 0;
});
db.warehouses.update({ "_id": doc._id }, doc );
})
Que é basicamente a maneira de atualizar todas elemento de matriz.
O multi configuração em
.update()
significa em vários "documentos". Ele não pode ser aplicado a vários elementos de uma matriz. Então, atualmente, a melhor opção é substituir a coisa toda. Ou, neste caso, podemos substituir o todo documento, pois precisamos fazer isso de qualquer maneira. Para real dados em massa, use db.eval() . Mas por favor leia a documentação primeiro:
db.eval(function() {
db.warehouses.find({ "items.qty": { "$gt": 0 } }).forEach(function(doc) {
doc.items.forEach(function(item) {
item.qty = 0;
});
db.warehouses.update({ "_id": doc._id }, doc );
});
})
Atualizando todos os elementos em uma matriz em todo coleta não é simples.
Original
Praticamente exatamente o que o erro diz. Para usar um operador posicional, você precisa corresponder algo primeiro. Como em:
db.warehouses.update(
// query
{
_id:ObjectId('5322f07e139cdd7e31178b78'),
"items.qty": { "$gt": 0 }
},
// update
{
$set:{"items.$.qty":0}
},
// options
{
"multi" : true,
"upsert" : true
}
);
Então, onde a corresponde condição termina a posição dos itens que são menos que 0 então esse índice é passado para o operador posicional.
PS :Quando mudar é verdadeiro significa que atualiza a cada documento. Deixe
false
se você quer dizer apenas um . Qual é o padrão.