Conforme mencionado, o principal problema aqui é com atualizações em vários elementos com o operador posicional, conforme registrado nesta edição de longa data:http://jira.mongodb.org/browse/SERVER-1243
O caso básico, portanto, é que nenhuma execução única pode fazer isso, portanto, para processar vários elementos de matriz, você precisa de algum método para determinar quantos elementos você precisa atualizar e processar uma instrução de atualização por cada elemento.
Uma abordagem simplificada para isso geralmente é usar Operações em massa para processar o que acaba sendo operações de atualização "múltiplas" como uma única solicitação e resposta ao servidor:
var bulk = db.collection.initializeOrderedBulkOp(),
count = 0;
db.collection.find({ "name": "John Doe", "adds.status": "PENDING" }).forEach(function(doc) {
doc.adds.filter(function(add){ return add.status = "PENDING" }).forEach(function(add) {
bulk.find({ "_id": doc._id, "adds.status": "PENDING" }).updateOne({
"$set": { "adds.$.status": "APPROVED" }
});
count++;
// Execute once in 1000 statements created and re-init
if ( count % 1000 == 0 ) {
bulk.execute();
bulk = db.collection.initializeOrderedBulkOp();
}
});
});
// Execute any pending operations
if ( count % 1000 != 0 )
bulk.execute();
Se seus documentos atualizados são muito pequenos, ou apenas um único documento, você pode renunciar ao
count
verifique e simplesmente anexe todas as atualizações em massa dentro dos loops necessários e execute apenas uma vez no final de todos os loops. Uma explicação mais longa e alternativas podem ser encontradas em Como atualizar vários elementos de matriz , mas todos se resumem a diferentes abordagens para combinar o elemento para atualizar e processar um posicional
$
atualize várias vezes, para cada documento correspondido ou até que não haja mais documentos modificados retornados.