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

Wie kann man eine große Anzahl von Dokumenten in MongoDB am effizientesten aktualisieren?

Wenn Ihr MongoDB-Server 2.6 oder neuer ist, wäre es besser, Schreibbefehle zu verwenden Bulk-API die die Ausführung von Massen-update Operationen, die einfach Abstraktionen auf dem Server sind, um das Erstellen von Massenoperationen zu vereinfachen. Diese Bulk-Operationen gibt es hauptsächlich in zwei Varianten:

  • Massenvorgänge bestellt . Diese Operationen führen alle Operationen der Reihe nach aus und geben beim ersten Schreibfehler einen Fehler aus.
  • Ungeordnete Massenvorgänge . Diese Operationen führen alle Operationen parallel aus und aggregieren alle Fehler. Ungeordnete Massenoperationen garantieren keine Ausführungsreihenfolge.

Beachten Sie, dass die API bei älteren Servern als 2.6 die Operationen herunterkonvertiert. Es ist jedoch nicht möglich, 100 % herunterzukonvertieren, daher kann es einige Grenzfälle geben, in denen die richtigen Zahlen nicht korrekt gemeldet werden können.

Für Ihre drei häufigsten Anwendungsfälle könnten Sie die Bulk-API wie folgt implementieren:

Fall 1. Ändern Sie den Werttyp der Eigenschaft, ohne den Wert zu ändern:

var MongoClient = require('mongodb').MongoClient;

MongoClient.connect("mongodb://localhost:27017/test", function(err, db) {
    // Handle error
    if(err) throw err;

    // Get the collection and bulk api artefacts
    var col = db.collection('users'),           
        bulk = col.initializeOrderedBulkOp(), // Initialize the Ordered Batch
        counter = 0;        

    // Case 1. Change type of value of property, without changing the value.        
    col.find({"timestamp": {"$exists": true, "$type": 2} }).each(function (err, doc) {

        var newTimestamp = parseInt(doc.timestamp);
        bulk.find({ "_id": doc._id }).updateOne({
            "$set": { "timestamp": newTimestamp }
        });

        counter++;

        if (counter % 1000 == 0 ) {
            bulk.execute(function(err, result) {  
                // re-initialise batch operation           
                bulk = col.initializeOrderedBulkOp();
            });
        }
    });

    if (counter % 1000 != 0 ){
        bulk.execute(function(err, result) {
            // do something with result
            db.close();
        }); 
    } 
});

Fall 2. Neue Eigenschaft basierend auf dem Wert der vorhandenen Eigenschaft hinzufügen:

MongoClient.connect("mongodb://localhost:27017/test", function(err, db) {
    // Handle error
    if(err) throw err;

    // Get the collection and bulk api artefacts
    var col = db.collection('users'),           
        bulk = col.initializeOrderedBulkOp(), // Initialize the Ordered Batch
        counter = 0;        

    // Case 2. Add new property based on value of existing property.        
    col.find({"name": {"$exists": false } }).each(function (err, doc) {

        var fullName = doc.firstname + " " doc.lastname;
        bulk.find({ "_id": doc._id }).updateOne({
            "$set": { "name": fullName }
        });

        counter++;

        if (counter % 1000 == 0 ) {
            bulk.execute(function(err, result) {  
                // re-initialise batch operation           
                bulk = col.initializeOrderedBulkOp();
            });
        }
    });

    if (counter % 1000 != 0 ){
        bulk.execute(function(err, result) {
            // do something with result
            db.close();
        }); 
    } 
});

Fall 3. Einfach Hinzufügen und Entfernen von Eigenschaften aus Dokumenten.

MongoClient.connect("mongodb://localhost:27017/test", function(err, db) {
    // Handle error
    if(err) throw err;

    // Get the collection and bulk api artefacts
    var col = db.collection('users'),           
        bulk = col.initializeOrderedBulkOp(), // Initialize the Ordered Batch
        counter = 0;        

    // Case 3. Simply adding removing properties from documents.    
    col.find({"street_no": {"$exists": true } }).each(function (err, doc) {

        bulk.find({ "_id": doc._id }).updateOne({
            "$set": { "no": doc.street_no },
            "$unset": { "street_no": "" }
        });

        counter++;

        if (counter % 1000 == 0 ) {
            bulk.execute(function(err, result) {  
                // re-initialise batch operation           
                bulk = col.initializeOrderedBulkOp();
            });
        }
    });

    if (counter % 1000 != 0 ){
        bulk.execute(function(err, result) {
            // do something with result
            db.close();
        }); 
    } 
});