Pour améliorer les performances, en particulier lorsque vous traitez de grandes collections, profitez de l'utilisation de Bulk()
API pour les mises à jour en bloc car vous enverrez les opérations au serveur par lots (par exemple, disons une taille de lot de 1000) ce qui vous donne de bien meilleures performances puisque vous n'enverrez pas toutes les requêtes au serveur (comme vous le faites actuellement faire avec l'instruction de mise à jour dans forEach()
boucle) mais une seule fois sur 1000 requêtes, ce qui rend vos mises à jour plus efficaces et plus rapides qu'actuellement.
Les exemples suivants illustrent cette approche, le premier utilise le Bulk()
API disponible dans les versions MongoDB >= 2.6 and < 3.2
. Il met à jour tous les documents dans les clients
collecte en changeant le nb_orders_1year
champs avec des valeurs issues des résultats de l'agrégation.
Depuis le Vous pouvez utiliser aggregate()
la méthode renvoie un cursor
,forEach()
méthode pour l'itérer et accéder à chaque document configurant ainsi les opérations de mise à jour en masse par lots pour ensuite les envoyer efficacement sur le serveur avec l'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(); }
L'exemple suivant s'applique à la nouvelle version de MongoDB 3.2
qui a depuis déprécié le Bulk API
et fourni un nouvel ensemble d'API en utilisant bulkWrite()
.
Il utilise le même curseur que ci-dessus mais au lieu d'itérer le résultat, créez le tableau avec les opérations en bloc en utilisant son map()
méthode :
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 });