Untuk meningkatkan kinerja terutama saat menangani koleksi besar, manfaatkan penggunaan Bulk()
API untuk pembaruan massal karena Anda akan mengirim operasi ke server dalam batch (misalnya, ukuran batch 1000) yang memberi Anda kinerja yang jauh lebih baik karena Anda tidak akan mengirim setiap permintaan ke server (seperti saat ini lakukan dengan pernyataan pembaruan dalam forEach()
loop) tetapi hanya sekali dalam setiap 1000 permintaan, sehingga membuat pembaruan Anda lebih efisien dan lebih cepat daripada saat ini.
Contoh berikut menunjukkan pendekatan ini, yang pertama menggunakan Bulk()
API tersedia dalam versi MongoDB >= 2.6 and < 3.2
. Ini memperbarui semua dokumen di clients
koleksi dengan mengubah nb_orders_1year
bidang dengan nilai dari hasil agregasi.
Sejak Anda dapat menggunakan koleksi keluaran agregasi aggregate()
metode mengembalikan cursor
,forEach()
metode untuk mengulanginya dan mengakses setiap dokumen sehingga menyiapkan operasi pembaruan massal dalam batch untuk kemudian dikirim ke seluruh server secara efisien dengan 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(); }
Contoh berikutnya berlaku untuk versi MongoDB baru 3.2
yang sejak menghentikan Massal API
dan menyediakan kumpulan api yang lebih baru menggunakan bulkWrite()
.
Ini menggunakan kursor yang sama seperti di atas tetapi alih-alih mengulangi hasilnya, buat array dengan operasi massal dengan menggunakan map()
metode:
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 });