Voor verbeterde prestaties, vooral bij het omgaan met grote collecties, kunt u profiteren van het gebruik van de Bulk()
API voor bulkupdates, aangezien u de bewerkingen in batches naar de server verzendt (bijvoorbeeld een batchgrootte van 1000), wat u veel betere prestaties geeft, omdat u niet elk verzoek naar de server verzendt (zoals u momenteel doet doen met de update-instructie in de forEach()
loop) maar slechts één keer op de 1000 verzoeken, waardoor uw updates efficiënter en sneller zijn dan nu het geval is.
De volgende voorbeelden demonstreren deze aanpak, de eerste gebruikt de Bulk()
API beschikbaar in MongoDB-versies >= 2.6 and < 3.2
. Het werkt alle documenten in de clients
. bij verzameling door het wijzigen van de nb_orders_1year
velden met waarden uit de aggregatieresultaten.
Sinds de U kunt de aggregate()
methode retourneert een cursor
,forEach()
methode om het te herhalen en toegang te krijgen tot elk document, waardoor de bulkupdate-bewerkingen in batches worden ingesteld om vervolgens efficiënt over de server te verzenden met de 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(); }
Het volgende voorbeeld is van toepassing op de nieuwe MongoDB-versie 3.2
die sindsdien de Bulk API
en leverde een nieuwere set api's met behulp van bulkWrite()
.
Het gebruikt dezelfde cursor als hierboven, maar in plaats van het resultaat te herhalen, maakt u de array met de bulkbewerkingen met behulp van de map()
methode:
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 });