Như đã đề cập, vấn đề chính ở đây là với các bản cập nhật trên nhiều phần tử với toán tử vị trí như đã được ghi trong vấn đề lâu đời này: http://jira.mongodb.org/browse/SERVER-1243
Do đó, trường hợp cơ bản là không một thực thi đơn lẻ nào có thể làm được điều này, vì vậy để xử lý nhiều phần tử mảng, bạn cần một số phương pháp xác định số lượng phần tử bạn cần cập nhật và xử lý một câu lệnh cập nhật cho mỗi phần tử.
Một cách tiếp cận đơn giản cho việc này thường là sử dụng Hoạt động hàng loạt để xử lý những gì kết thúc là hoạt động cập nhật "nhiều" dưới dạng một yêu cầu và phản hồi duy nhất tới máy chủ:
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();
Nếu tài liệu được cập nhật của bạn khá nhỏ hoặc thực sự chỉ là một tài liệu thì bạn có thể bỏ qua count
kiểm tra và chỉ cần nối tất cả các cập nhật hàng loạt trong các vòng bắt buộc và chỉ thực thi một lần ở cuối tất cả các vòng.
Bạn có thể tìm thấy giải thích dài hơn và các thay thế trên Cách cập nhật nhiều phần tử mảng
, nhưng tất cả đều đi đến các cách tiếp cận khác nhau để đối sánh phần tử để cập nhật và xử lý vị trí $
cập nhật nhiều lần, cho từng tài liệu khớp hoặc cho đến khi không còn tài liệu sửa đổi nào được trả lại.