前述のように、ここでの主な問題は、この長年の問題に記録されている位置演算子を使用した複数の要素の更新です。 http://jira.mongodb.org/browse/SERVER-1243
したがって、基本的なケースでは、1回の実行でこれを実行することはできません。したがって、複数の配列要素を処理するには、更新する必要のある要素の数を決定し、要素ごとに1つの更新ステートメントを処理する方法が必要です。
これに対する単純化されたアプローチは、通常、バルク操作 を使用することです。 最終的に「複数の」更新操作になるものを、サーバーへの単一の要求と応答として処理するには:
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();
更新されたドキュメントが非常に小さい場合、または実際に1つのドキュメントしかない場合は、count
を忘れることができます。 必要なループ内のすべての一括更新を確認して追加し、すべてのループの最後に1回だけ実行します。
より長い説明と代替案は、複数の配列要素を更新する方法
にあります。 、しかしすべては、要素を一致させて位置$
一致したドキュメントごとに、または変更されたドキュメントが返されなくなるまで、複数の時間を更新します。