sql >> Database >  >> NoSQL >> MongoDB

Knooppunt voegt grote gegevens in met mangoest

Het probleem hier is dat de lus die u uitvoert niet wacht tot elke bewerking is voltooid. Dus in feite zet je gewoon duizenden .save() in de rij verzoeken en proberen ze gelijktijdig uit te voeren. Je kunt dat niet doen binnen redelijke beperkingen, daarom krijg je de foutmelding.

De async module heeft verschillende methoden voor iteratie tijdens het verwerken van een callback voor die iterator, waarbij waarschijnlijk de meest eenvoudige directe voor terwijl . Mongoose zorgt ook voor het verbindingsbeheer voor u zonder dat u zich hoeft in te sluiten in de callback, omdat de modellen verbindingsbewust zijn:

var tempColSchema = new Schema({
    cid: {
        type: Number,
        required: true
    },
    loc:[]
});

var TempCol = mongoose.model( "TempCol", tempColSchema );

mongoose.connect( 'mongodb://localhost/mean-dev' );

var i = 0;
async.whilst(
    function() { return i < 10000000; },
    function(callback) {
        i++;
        var c = i;
        console.log(c);
        var lon = parseInt(c/100000);
        var lat = c%100000;
        new Tempcol({cid: Math.random(), loc: [lon, lat]}).save(function(err){
            callback(err);
        });            
    },
    function(err) {
       // When the loop is complete or on error
    }
);

Niet de meest fantastische manier om het te doen, het is nog steeds één keer schrijven en je zou andere methoden kunnen gebruiken om de gelijktijdige bewerkingen te "regeren", maar dit zal in ieder geval de call-stack niet opblazen.

Vanaf MongoDB 2.6 en hoger kunt u gebruik maken van de Bulk Operations API om meer dan één schrijven tegelijk op de server te verwerken. Het proces is dus vergelijkbaar, maar deze keer kun je 1000 tegelijk naar de server sturen in één keer schrijven en reageren, wat veel sneller is:

var tempColSchema = new Schema({
    cid: {
        type: Number,
        required: true
    },
    loc:[]
});

var TempCol = mongoose.model( "TempCol", tempColSchema );

mongoose.connect( 'mongodb://localhost/mean-dev' );

mongoose.on("open",function(err,conn) {

    var i = 0;
    var bulk = TempCol.collection.initializeOrderedBulkOp();

    async.whilst(
      function() { return i < 10000000; },
      function(callback) {
        i++;
        var c = i;
        console.log(c);
        var lon = parseInt(c/100000);
        var lat = c%100000;

        bulk.insert({ "cid": Math.random(), "loc": [ lon, lat ] });

        if ( i % 1000 == 0 ) {
            bulk.execute(function(err,result) {
                bulk = TempCol.collection.initializeOrderedBulkOp();
                callback(err);
            });
        } else {
            process.nextTick(callback);
        }
      },
      function(err) {
        // When the loop is complete or on error

        // If you had a number not plainly divisible by 1000
        if ( i % 1000 != 0 )
            bulk.execute(function(err,result) {
                // possibly check for errors here
            });
      }
    );

});

Dat is eigenlijk het gebruik van de native driver-methoden die nog niet zijn blootgesteld in mangoest, dus de extra zorg wordt genomen om ervoor te zorgen dat de verbinding beschikbaar is. Dat is een voorbeeld, maar niet de enige manier, maar het belangrijkste punt is dat de mangoest "magie" voor verbindingen hier niet is ingebouwd, dus je moet er zeker van zijn dat het tot stand is gebracht.

U moet een rond aantal items verwerken, maar als dit niet het geval is, moet u de bulk.execute() aanroepen in dat laatste blok evenals getoond, maar het hangt af van het nummer dat reageert op de modulo.

Het belangrijkste punt is om een ​​stapel bewerkingen niet tot een onredelijke omvang te laten groeien en de verwerking beperkt te houden. De stroomregeling hier maakt bewerkingen mogelijk die enige tijd duren voordat ze daadwerkelijk zijn voltooid voordat ze naar de volgende iteratie gaan. Dus ofwel de batch-updates of wat extra parallelle wachtrijen is wat je wilt voor de beste prestaties.

Er is ook de .initializeUnorderedBulkOp() formulier hiervoor als u niet wilt dat schrijffouten fataal zijn, maar in plaats daarvan op een andere manier omgaat. Zie vooral de officiële documentatie over Bulk API en antwoorden voor hoe u het gegeven antwoord moet interpreteren.




  1. Werk genest object in MongoDB bij als het bestaat, voeg het anders toe

  2. meerdere documenten invoegen met behulp van mongoengine in mongodb

  3. Tijdstempel tot nu toe in php en mongodb

  4. MongoDB:update het hele document behalve _id met behulp van C#-stuurprogramma