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); }