Come accennato, il problema principale qui riguarda gli aggiornamenti su più elementi con l'operatore posizionale come registrato in questo numero di vecchia data:http://jira.mongodb.org/browse/SERVER-1243
Il caso di base quindi è che nessuna singola esecuzione può farlo, quindi per elaborare più elementi dell'array è necessario un metodo per determinare quanti elementi sono necessari per aggiornare ed elaborare un'istruzione di aggiornamento per ciascun elemento.
Un approccio semplificato a questo è generalmente l'utilizzo di Operazioni in blocco per elaborare quelle che finiscono per essere operazioni di aggiornamento "multiple" come una singola richiesta e risposta al server:
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 i tuoi documenti aggiornati sono piuttosto piccoli, o addirittura solo un singolo documento, puoi rinunciare al count
controlla e aggiungi semplicemente tutti gli aggiornamenti in blocco all'interno dei loop richiesti ed esegui semplicemente una volta alla fine di tutti i loop.
Una spiegazione più lunga e alternative sono disponibili su Come aggiornare più elementi di array
, ma tutti si riducono a approcci diversi per abbinare l'elemento per aggiornare ed elaborare un posizionale $
aggiorna più volte, per ogni documento abbinato o fino a quando non ci sono più documenti modificati restituiti.