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

MongoDB:Copiando um array para outro array no mesmo documento


Para dados relativamente pequenos, você pode obter o acima, iterando a coleção usando um snapshot com o forEach() do cursor e atualizando cada documento da seguinte forma:
db.wholesalers.find({ 
    "brands": { "$exists": true, "$type": 4 } 
}).snapshot().forEach(function(doc){ 
    db.wholesalers.updateOne(
        { "_id": doc._id },
        { "$set": { "brandsNetherlands": doc.brands } }
    );
});

Embora isso seja ideal para coleções pequenas, o desempenho com coleções grandes é bastante reduzido, pois fazer um loop em um grande conjunto de dados e enviar cada operação de atualização por solicitação ao servidor incorre em uma penalidade computacional.

O Bulk() A API vem em socorro e melhora muito o desempenho, pois as operações de gravação são enviadas ao servidor apenas uma vez em massa. A eficiência é alcançada porque o método não envia todas as solicitações de gravação para o servidor (como na declaração de atualização atual no forEach() loop), mas apenas uma vez a cada 1.000 solicitações, tornando as atualizações mais eficientes e rápidas do que atualmente.

Usando o mesmo conceito acima com o forEach() loop para criar os lotes, podemos atualizar a coleção em massa da seguinte maneira.

Nesta demonstração, o Bulk() API disponível nas versões do MongoDB >= 2.6 and < 3.2 usa o initializeUnorderedBulkOp() método para executar em paralelo, bem como em uma ordem não determinística, as operações de gravação nos lotes:

var bulk =db.wholesalers.initializeUnorderedBulkOp(),counter =0; // contador para acompanhar o tamanho da atualização do lote
db.wholesalers.find({ 
    "brands": { "$exists": true, "$type": 4 } 
}).snapshot().forEach(function(doc){ 

    bulk.find({ "_id": doc._id }).updateOne({ 
        "$set": { "brandsNetherlands": doc.brands } 
    });

    counter++; // increment counter
    if (counter % 1000 == 0) {
        bulk.execute(); // Execute per 1000 operations and re-initialize every 1000 update statements
        bulk = db.wholesalers.initializeUnorderedBulkOp();
    }
});

O próximo exemplo se aplica à nova versão do MongoDB 3.2 que desde então desativou o Bulk() API e forneceu um conjunto mais recente de APIs usando bulkWrite() .

Ele usa os mesmos cursores acima, mas cria os arrays com as operações em massa usando o mesmo forEach() cursor para enviar cada documento de gravação em massa para a matriz. Como os comandos de gravação não podem aceitar mais de 1.000 operações, é necessário agrupar as operações para ter no máximo 1.000 operações e reinicializar a matriz quando o loop atingir a iteração 1.000:
var cursor = db.wholesalers.find({
         "brands": { "$exists": true, "$type": 4 } 
    }),
    bulkUpdateOps = [];

cursor.snapshot().forEach(function(doc){ 
    bulkUpdateOps.push({ 
        "updateOne": {
            "filter": { "_id": doc._id },
            "update": { "$set": { "brandsNetherlands": doc.brands } }
         }
    });

    if (bulkUpdateOps.length === 1000) {
        db.wholesalers.bulkWrite(bulkUpdateOps);
        bulkUpdateOps = [];
    }
});         

if (bulkUpdateOps.length > 0) { db.wholesalers.bulkWrite(bulkUpdateOps); }