MongoDB
 sql >> Base de Dados >  >> NoSQL >> MongoDB

Agregar e atualizar o MongoDB


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.

Desde o aggregate() retorna um cursor , Você pode usar o 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 });