Jak wspomniano, głównym problemem są tutaj aktualizacje wielu elementów z operatorem pozycyjnym, jak opisano w tym istniejącym od dawna problemie:http://jira.mongodb.org/browse/SERVER-1243
Podstawowym przypadkiem jest zatem to, że żadne pojedyncze wykonanie nie może tego zrobić, więc aby przetworzyć wiele elementów tablicy, potrzebujesz jakiejś metody określania, ile elementów musisz zaktualizować i przetworzyć jedną instrukcję aktualizacji na każdy element.
Uproszczonym podejściem do tego jest zazwyczaj użycie Operacje zbiorcze aby przetworzyć to, co kończy się "wieloma" operacjami aktualizacji jako pojedyncze żądanie i odpowiedź do serwera:
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();
Jeśli zaktualizowane dokumenty są dość małe, a nawet tylko jeden dokument, możesz zrezygnować z count
sprawdź i po prostu dołącz wszystkie aktualizacje zbiorcze w wymaganych pętlach i po prostu wykonaj raz na końcu wszystkich pętli.
Dłuższe wyjaśnienie i alternatywne rozwiązania można znaleźć w Jak zaktualizować wiele elementów tablicy
, ale wszystkie sprowadzają się do różnych podejść do dopasowania elementu do aktualizacji i przetwarzania pozycyjny $
aktualizuj wiele razy, dla każdego dopasowanego dokumentu lub do momentu, gdy nie zostaną zwrócone żadne zmodyfikowane dokumenty.