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

Node indsæt store data ved hjælp af mongoose

Problemet her er, at den løkke, du kører, ikke venter på, at hver operation er fuldført. Så faktisk står du bare i kø i 1000-vis af .save() anmodninger og forsøger at køre dem samtidigt. Du kan ikke gøre det inden for rimelige begrænsninger, derfor får du fejlsvaret.

async modul har forskellige metoder til iteration, mens der behandles et tilbagekald for den iterator, hvor den nok mest enkle direkte for er mens . Mongoose håndterer også forbindelsesstyringen for dig uden at skulle integrere i tilbagekaldet, da modellerne er forbindelsesbevidste:

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

Ikke den mest fantastiske måde at gøre det på, det er stadig en skrivning ad gangen, og du kan bruge andre metoder til at "styre" de samtidige operationer, men dette vil i det mindste ikke sprænge opkaldsstakken.

Form MongoDB 2.6 og nyere kan du gøre brug af Bulk Operations API for at behandle mere end én skrivning ad gangen på serveren. Så processen ligner, men denne gang kan du sende 1000 ad gangen til serveren i en enkelt skrivning og svar, hvilket er meget hurtigere:

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

});

Det er faktisk at bruge de native driver-metoder, som endnu ikke er afsløret i mongoose, så den ekstra omhu der bliver taget for at sikre, at forbindelsen er tilgængelig. Det er et eksempel, men ikke den eneste måde, men hovedpointen er, at mangust-"magien" for forbindelser ikke er indbygget her, så du skal være sikker på, at den er etableret.

Du har et rundt antal elementer at behandle, men hvor det ikke er tilfældet, skal du kalde bulk.execute() i den sidste blok samt vist, men det afhænger af antallet, der svarer på modulo.

Hovedpointen er ikke at vokse en stak operationer til en urimelig størrelse og holde behandlingen begrænset. Flowstyringen her tillader operationer, der vil tage noget tid at gennemføre, før du går videre til næste iteration. Så enten batchopdateringerne eller en ekstra parallel kø er det, du ønsker for den bedste ydeevne.

Der er også .initializeUnorderedBulkOp() formular til dette, hvis du ikke ønsker at skrivefejl skal være fatale, men håndtere dem på en anden måde i stedet. Se for det meste den officielle dokumentation om Bulk API og svar for, hvordan man fortolker svaret.




  1. MongoError ukendt topniveauoperatør:$set

  2. MongoDB:Hvordan grupperes indlejrede arrays i ét dokument?

  3. Mongodb c# driver og ISODate

  4. Sådan henter du detaljerne fra mongo db og sender eller gemmer i objekt i nodejs Fork-metoden