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

Il nodo inserisce dati di grandi dimensioni usando la mangusta

Il problema qui è che il ciclo in esecuzione non attende il completamento di ciascuna operazione. Quindi in effetti stai solo mettendo in coda migliaia di .save() richieste e provando a eseguirle contemporaneamente. Non puoi farlo entro limiti ragionevoli, quindi ottieni la risposta di errore.

Il async modulo ha vari metodi per l'iterazione durante l'elaborazione di una callback per quell'iteratore, dove probabilmente il diretto più semplice per è mentre . Mongoose gestisce anche la gestione della connessione per te senza bisogno di incorporare nella richiamata, poiché i modelli sono consapevoli della connessione:

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

Non è il modo più fantastico per farlo, è ancora una scrittura alla volta e potresti usare altri metodi per "governare" le operazioni simultanee, ma questo almeno non farà esplodere lo stack delle chiamate.

Da MongoDB 2.6 e versioni successive puoi utilizzare l'API per le operazioni in blocco per elaborare più di una scrittura alla volta sul server. Quindi il processo è simile, ma questa volta puoi inviarne 1000 alla volta al server in un'unica scrittura e risposta, il che è molto più veloce:

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

});

Ciò sta effettivamente utilizzando i metodi del driver nativo che non sono ancora esposti in mangusta, quindi viene prestata ulteriore attenzione per assicurarsi che la connessione sia disponibile. Questo è un esempio ma non l'unico modo, ma il punto principale è che la "magia" della mangusta per le connessioni non è integrata qui, quindi dovresti essere sicuro che sia stabilita.

Hai un numero tondo di elementi da elaborare, ma dove non è il caso dovresti chiamare bulk.execute() in quell'ultimo blocco così come mostrato, ma dipende dal numero che risponde al modulo.

Il punto principale è non far crescere una pila di operazioni a una dimensione irragionevole e mantenere l'elaborazione limitata. Il controllo del flusso qui consente operazioni che richiedono del tempo per essere effettivamente completate prima di passare all'iterazione successiva. Quindi o gli aggiornamenti in batch o alcune code parallele aggiuntive sono ciò che desideri per le migliori prestazioni.

C'è anche il .initializeUnorderedBulkOp() modulo per questo se non vuoi che gli errori di scrittura siano fatali ma gestirli invece in un modo diverso. Per lo più, consulta la documentazione ufficiale sull'API Bulk e le risposte su come interpretare la risposta fornita.