Để cải thiện hiệu suất, đặc biệt là khi xử lý các bộ sưu tập lớn, hãy tận dụng lợi thế của việc sử dụng Bulk()
API để cập nhật hàng loạt vì bạn sẽ gửi các hoạt động đến máy chủ theo lô (ví dụ:kích thước lô là 1000) mang lại cho bạn hiệu suất tốt hơn nhiều vì bạn sẽ không gửi mọi yêu cầu đến máy chủ (như hiện tại thực hiện với câu lệnh cập nhật trong forEach()
loop) nhưng chỉ một lần trong mỗi 1000 yêu cầu, do đó làm cho các bản cập nhật của bạn hiệu quả hơn và nhanh hơn hiện tại.
Các ví dụ sau đây chứng minh cách tiếp cận này, cách đầu tiên sử dụng Bulk()
API có sẵn trong các phiên bản MongoDB >= 2.6 and < 3.2
. Nó cập nhật tất cả các tài liệu trong clients
bộ sưu tập bằng cách thay đổi nb_orders_1year
các trường có giá trị từ kết quả tổng hợp.
Vì Bạn có thể sử dụng tập hợp đầu ra tổng hợp aggregate()
phương thức trả về một cursor
, forEach()
để lặp lại nó và truy cập từng tài liệu, do đó thiết lập các hoạt động cập nhật hàng loạt theo lô để sau đó gửi qua máy chủ một cách hiệu quả với API:
var bulk = db.clients.initializeUnorderedBulkOp(),
pipeline = [
{
"$match": { "date_order": { "$gt": v_date1year } }
},
{
"$group": {
"_id": "$id_client",
"count": { "$sum" : 1 }
}
},
{ "$out": "tmp_indicators" }
],
counter = 0;
db.orders.aggregate(pipeline);
db.tmp_indicators.find().forEach(function (doc) {
bulk.find({ "_id": doc._id }).updateOne({
"$set": { "nb_orders_1year": doc.count }
});
counter++;
if (counter % 1000 == 0) {
bulk.execute(); // Execute per 1000 operations and re-initialize every 1000 update statements
bulk = db.clients.initializeUnorderedBulkOp();
}
});
// Clean up remaining operations in queue
if (counter % 1000 != 0) { bulk.execute(); }
Ví dụ tiếp theo áp dụng cho phiên bản MongoDB mới 3.2
từ đó không dùng Bulk nữa 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ùng một con trỏ như trên nhưng thay vì lặp lại kết quả, hãy tạo mảng với các phép toán hàng loạt bằng cách sử dụng map()
phương pháp:
var pipeline = [
{
"$match": { "date_order": { "$gt": v_date1year } }
},
{
"$group": {
"_id": "$id_client",
"count": { "$sum" : 1 }
}
},
{ "$out": "tmp_indicators" }
];
db.orders.aggregate(pipeline);
var bulkOps = db.tmp_indicators.find().map(function (doc) {
return {
"updateOne": {
"filter": { "_id": doc._id } ,
"update": { "$set": { "nb_orders_1year": doc.count } }
}
};
});
db.clients.bulkWrite(bulkOps, { "ordered": true });