sql >> Base de Datos >  >> NoSQL >> MongoDB

MongoDB:copiando una matriz a otra matriz en el mismo documento

Para datos relativamente pequeños, puede lograr lo anterior iterando la colección usando un snapshot con el cursor forEach() y actualizando cada documento de la siguiente manera:

db.wholesalers.find({ 
    "brands": { "$exists": true, "$type": 4 } 
}).snapshot().forEach(function(doc){ 
    db.wholesalers.updateOne(
        { "_id": doc._id },
        { "$set": { "brandsNetherlands": doc.brands } }
    );
});

Si bien esto es óptimo para colecciones pequeñas, el rendimiento con colecciones grandes se reduce considerablemente, ya que recorrer un gran conjunto de datos y enviar cada operación de actualización por solicitud al servidor incurre en una penalización computacional.

El Bulk() La API viene al rescate y mejora en gran medida el rendimiento, ya que las operaciones de escritura se envían al servidor solo una vez de forma masiva. La eficiencia se logra ya que el método no envía cada solicitud de escritura al servidor (como con la declaración de actualización actual dentro de forEach() loop), pero solo una de cada 1000 solicitudes, lo que hace que las actualizaciones sean más eficientes y rápidas de lo que es actualmente.

Usando el mismo concepto anterior con forEach() bucle para crear los lotes, podemos actualizar la colección de forma masiva de la siguiente manera.

En esta demostración, Bulk() API disponible en las versiones de MongoDB >= 2.6 and < 3.2 utiliza el initializeUnorderedBulkOp() método para ejecutar en paralelo, así como en un orden no determinista, las operaciones de escritura en los lotes:

var bulk =db.wholesalers.initializeUnorderedBulkOp(),counter =0; // contador para realizar un seguimiento del tamaño de actualización por lotes

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

El siguiente ejemplo se aplica a la nueva versión de MongoDB 3.2 que desde entonces ha obsoleto el Bulk() API y proporcionó un conjunto más nuevo de apis usando bulkWrite() .

Utiliza los mismos cursores que el anterior pero crea las matrices con las operaciones masivas usando el mismo forEach() método de cursor para enviar cada documento de escritura masiva a la matriz. Debido a que los comandos de escritura no pueden aceptar más de 1000 operaciones, es necesario agrupar las operaciones para tener como máximo 1000 operaciones y reinicializar la matriz cuando el bucle llega a la iteración 1000:

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