MongoDB
 sql >> Datenbank >  >> NoSQL >> MongoDB

MongoDB:Kopieren eines Arrays in ein anderes Array im selben Dokument

Bei relativ kleinen Daten können Sie dies erreichen, indem Sie die Sammlung mit einem snapshot mit dem forEach() des Cursors Methode und Aktualisierung jedes Dokuments wie folgt:

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

Während dies für kleine Sammlungen optimal ist, wird die Leistung bei großen Sammlungen stark reduziert, da das Schleifen durch einen großen Datensatz und das Senden jeder Aktualisierungsoperation pro Anfrage an den Server eine Rechenstrafe nach sich zieht.

Der Bulk() Die API kommt zu Hilfe und verbessert die Leistung erheblich, da Schreibvorgänge nur einmal in großen Mengen an den Server gesendet werden. Die Effizienz wird erreicht, da die Methode nicht jede Schreibanforderung an den Server sendet (wie bei der aktuellen Update-Anweisung im forEach() -Schleife), sondern nur einmal alle 1000 Anfragen, wodurch Aktualisierungen effizienter und schneller werden als derzeit.

Verwenden des gleichen Konzepts oben mit dem forEach() -Schleife zum Erstellen der Stapel verwenden, können wir die Sammlung wie folgt in großen Mengen aktualisieren.

In dieser Demonstration ist Bulk() API verfügbar in den MongoDB-Versionen >= 2.6 and < 3.2 verwendet den initializeUnorderedBulkOp() Methode, um die Schreiboperationen in den Stapeln parallel sowie in nicht deterministischer Reihenfolge auszuführen:

var bulk =db.wholesalers.initializeUnorderedBulkOp(),counter =0; // Zähler, um die Größe der Stapelaktualisierung zu verfolgen

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

Das nächste Beispiel gilt für die neue MongoDB-Version 3.2 die seitdem den Bulk() als veraltet markiert hat API und stellte einen neueren Satz von APIs mit bulkWrite() .

Es verwendet die gleichen Cursor wie oben, erstellt aber die Arrays mit den Massenoperationen unter Verwendung des gleichen forEach() Cursor-Methode, um jedes Massenschreibdokument in das Array zu verschieben. Da Schreibbefehle nicht mehr als 1000 Operationen akzeptieren können, müssen Operationen so gruppiert werden, dass sie höchstens 1000 Operationen haben, und das Array neu initialisieren, wenn die Schleife die 1000 Iteration erreicht:

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