Đối với dữ liệu tương đối nhỏ, bạn có thể đạt được điều trên bằng cách lặp lại bộ sưu tập bằng cách sử dụng snapshot
với forEach()
của con trỏ
phương pháp và cập nhật từng tài liệu như sau:
db.wholesalers.find({
"brands": { "$exists": true, "$type": 4 }
}).snapshot().forEach(function(doc){
db.wholesalers.updateOne(
{ "_id": doc._id },
{ "$set": { "brandsNetherlands": doc.brands } }
);
});
Trong khi điều này là tối ưu cho các bộ sưu tập nhỏ, hiệu suất với các bộ sưu tập lớn bị giảm đáng kể vì việc lặp qua một tập dữ liệu lớn và gửi từng thao tác cập nhật cho mỗi yêu cầu tới máy chủ sẽ phải chịu một hình phạt tính toán.
Bulk()
API ra đời để giải cứu và cải thiện đáng kể hiệu suất vì các hoạt động ghi chỉ được gửi đến máy chủ một lần với số lượng lớn. Hiệu quả đạt được vì phương pháp không gửi mọi yêu cầu ghi tới máy chủ (như với câu lệnh cập nhật hiện tại trong forEach()
loop) nhưng chỉ một lần trong mỗi 1000 yêu cầu, do đó, cập nhật hiệu quả hơn và nhanh hơn hiện tại.
Sử dụng khái niệm tương tự ở trên với forEach()
vòng lặp để tạo các lô, chúng ta có thể cập nhật hàng loạt bộ sưu tập như sau.
Trong phần trình diễn này, Bulk()
API có sẵn trong các phiên bản MongoDB >= 2.6 and < 3.2
sử dụng initializeUnorderedBulkOp()
để thực thi song song, cũng như theo thứ tự không xác định, các thao tác ghi trong lô:
var Bulk =db.wholesalers.initializeUnorderedBulkOp (), counter =0; // bộ đếm để theo dõi kích thước cập nhật hàng loạt
db.wholesalers.find({
"brands": { "$exists": true, "$type": 4 }
}).snapshot().forEach(function(doc){
bulk.find({ "_id": doc._id }).updateOne({
"$set": { "brandsNetherlands": doc.brands }
});
counter++; // increment counter
if (counter % 1000 == 0) {
bulk.execute(); // Execute per 1000 operations and re-initialize every 1000 update statements
bulk = db.wholesalers.initializeUnorderedBulkOp();
}
});
Ví dụ tiếp theo áp dụng cho phiên bản MongoDB mới 3.2
từ đó không dùng nữa Bulk()
API và cung cấp một tập hợp apis mới hơn bằng cách sử dụng bulkWrite()
.
Nó sử dụng các con trỏ tương tự như trên nhưng tạo các mảng với các hoạt động hàng loạt bằng cách sử dụng cùng một forEach()
phương thức con trỏ để đẩy từng tài liệu ghi số lượng lớn vào mảng. Bởi vì lệnh ghi có thể chấp nhận không quá 1000 hoạt động, cần phải nhóm các hoạt động để có nhiều nhất 1000 hoạt động và tổ chức lại mảng khi vòng lặp đạt đến 1000 lần lặp:
var cursor = db.wholesalers.find({
"brands": { "$exists": true, "$type": 4 }
}),
bulkUpdateOps = [];
cursor.snapshot().forEach(function(doc){
bulkUpdateOps.push({
"updateOne": {
"filter": { "_id": doc._id },
"update": { "$set": { "brandsNetherlands": doc.brands } }
}
});
if (bulkUpdateOps.length === 1000) {
db.wholesalers.bulkWrite(bulkUpdateOps);
bulkUpdateOps = [];
}
});
if (bulkUpdateOps.length > 0) { db.wholesalers.bulkWrite(bulkUpdateOps); }