Como se mencionó, el problema principal aquí es con las actualizaciones de múltiples elementos con el operador posicional como se registra en este problema de larga data:http://jira.mongodb.org/browse/SERVER-1243
Por lo tanto, el caso básico es que ninguna ejecución única puede hacer esto, por lo que para procesar múltiples elementos de matriz, necesita algún método para determinar cuántos elementos necesita actualizar y procesar una instrucción de actualización para cada elemento.
Un enfoque simplificado para esto es generalmente usar Operaciones masivas para procesar lo que termina siendo "múltiples" operaciones de actualización como una sola solicitud y respuesta al 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();
Si sus documentos actualizados son bastante pequeños, o de hecho solo un documento, puede renunciar al count
verifique y simplemente agregue todas las actualizaciones masivas dentro de los bucles requeridos y simplemente ejecute una vez al final de todos los bucles.
Se puede encontrar una explicación más larga y alternativas en Cómo actualizar varios elementos de matriz
, pero todos se reducen a diferentes enfoques para hacer coincidir el elemento para actualizar y procesar un posicional $
actualice varias veces, ya sea para cada documento coincidente o hasta que no se devuelvan más documentos modificados.