Para melhorar o desempenho, especialmente ao lidar com grandes coleções, aproveite o uso do
Bulk()
API para atualizações em massa, pois você enviará as operações para o servidor em lotes (por exemplo, um tamanho de lote de 1000), o que oferece um desempenho muito melhor, pois você não enviará todas as solicitações ao servidor (como você está atualmente fazendo com a instrução de atualização dentro do forEach()
loop), mas apenas uma vez a cada 1.000 solicitações, tornando suas atualizações mais eficientes e rápidas do que atualmente. Os exemplos a seguir demonstram essa abordagem, o primeiro usa o
Bulk()
API disponível nas versões do MongoDB >= 2.6 and < 3.2
. Ele atualiza todos os documentos nos clients
coleção alterando o nb_orders_1year
campos com valores dos resultados de agregação. aggregate()
retorna um cursor
,forEach()
método para iterar e acessar cada documento, configurando as operações de atualização em massa em lotes para então enviar pelo servidor de forma eficiente com a 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(); }
O próximo exemplo se aplica à nova versão do MongoDB
3.2
que desde então obsolicitou o Bulk API
e forneceu um conjunto mais recente de APIs usando bulkWrite()
. Ele usa o mesmo cursor acima, mas em vez de iterar o resultado, crie a matriz com as operações em massa usando seu
map()
método: 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 });