Aby poprawić wydajność, zwłaszcza w przypadku dużych kolekcji, skorzystaj z Bulk()
Interfejs API do aktualizacji zbiorczych, ponieważ będziesz wysyłać operacje do serwera w partiach (na przykład rozmiar partii 1000), co zapewnia znacznie lepszą wydajność, ponieważ nie będziesz wysyłać wszystkich żądań do serwera (jak obecnie robienie z instrukcją aktualizacji w forEach()
pętla), ale tylko raz na 1000 żądań, dzięki czemu aktualizacje są wydajniejsze i szybsze niż obecnie.
Poniższe przykłady demonstrują to podejście, pierwszy używa Bulk()
API dostępne w wersjach MongoDB >= 2.6 and < 3.2
. Aktualizuje wszystkie dokumenty w clients
kolekcja, zmieniając nb_orders_1year
pola z wartościami z wyników agregacji.
Od Możesz użyć kolekcji danych wyjściowych agregacji aggregate()
metoda zwraca cursor
,forEach()
metoda iteracji i uzyskiwania dostępu do każdego dokumentu, w ten sposób konfigurując operacje zbiorczej aktualizacji w partiach, aby następnie efektywnie wysyłać je przez serwer za pomocą interfejsu 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(); }
Następny przykład dotyczy nowej wersji MongoDB 3.2
która od czasu wycofała się z Bulk API
i dostarczył nowszy zestaw interfejsów API przy użyciu bulkWrite()
.
Używa tego samego kursora, co powyżej, ale zamiast iterować wynik, utwórz tablicę z operacjami zbiorczymi, używając jej map()
metoda:
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 });