MongoDB
 sql >> Database >  >> NoSQL >> MongoDB

MongoDB:copia di un array in un altro array nello stesso documento

Per dati relativamente piccoli, puoi ottenere quanto sopra ripetendo la raccolta utilizzando un snapshot con forEach() del cursore metodo e aggiornando ogni documento come segue:

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

Sebbene ciò sia ottimale per raccolte di piccole dimensioni, le prestazioni con raccolte di grandi dimensioni sono notevolmente ridotte poiché il looping di un set di dati di grandi dimensioni e l'invio di ogni operazione di aggiornamento per richiesta al server comporta una penalità computazionale.

Il Bulk() L'API viene in soccorso e migliora notevolmente le prestazioni poiché le operazioni di scrittura vengono inviate al server solo una volta in blocco. L'efficienza è raggiunta poiché il metodo non invia tutte le richieste di scrittura al server (come con l'attuale dichiarazione di aggiornamento all'interno di forEach() loop) ma solo una volta ogni 1000 richieste, rendendo così gli aggiornamenti più efficienti e rapidi di quanto non lo siano attualmente.

Utilizzando lo stesso concetto sopra con forEach() loop per creare i batch, possiamo aggiornare la raccolta in blocco come segue.

In questa dimostrazione il Bulk() API disponibile nelle versioni MongoDB >= 2.6 and < 3.2 utilizza il initializeUnorderedBulkOp() metodo per eseguire in parallelo, oltre che in ordine non deterministico, le operazioni di scrittura nei batch:

var bulk =db.wholesalers.initializeUnorderedBulkOp(),counter =0; // contatore per tenere traccia della dimensione dell'aggiornamento batch

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

Il prossimo esempio si applica alla nuova versione di MongoDB 3.2 che da allora ha deprecato il Bulk() API e fornito un set più recente di API utilizzando bulkWrite() .

Utilizza gli stessi cursori di cui sopra ma crea gli array con le operazioni di massa utilizzando lo stesso forEach() cursore per eseguire il push di ogni documento di scrittura in blocco nell'array. Poiché i comandi di scrittura non possono accettare più di 1000 operazioni, è necessario raggruppare le operazioni per avere al massimo 1000 operazioni e reinizializzare l'array quando il ciclo raggiunge l'iterazione 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); }