Det exploderade eftersom du inte väntar på att ett asynkront samtal ska slutföras innan du går vidare till nästa iteration. Vad detta betyder är att du bygger en "stack" av olösta operationer tills detta orsakar ett problem. Vad heter den här sidan igen? Skaffa bilden?
Så det här är inte det bästa sättet att gå vidare med "Bulk"
insättningar. Lyckligtvis har den underliggande MongoDB-drivrutinen redan tänkt på detta, bortsett från återuppringningsproblemet som nämnts tidigare. Det finns faktiskt ett "Bulk API"
tillgänglig för att göra detta mycket bättre. Och förutsatt att du redan har hämtat den ursprungliga drivrutinen som db
objekt. Men jag föredrar att bara använda .collection
accessor från modellen och "async"
modul för att göra allt klart:
var bulk = Model.collection.initializeOrderedBulkOp();
var counter = 0;
async.whilst(
// Iterator condition
function() { return count < 1000000 },
// Do this in the iterator
function(callback) {
counter++;
var model = buildModel(counter);
bulk.insert(model);
if ( counter % 1000 == 0 ) {
bulk.execute(function(err,result) {
bulk = Model.collection.initializeOrderedBulkOp();
callback(err);
});
} else {
callback();
}
},
// When all is done
function(err) {
if ( counter % 1000 != 0 )
bulk.execute(function(err,result) {
console.log( "inserted some more" );
});
console.log( "I'm finished now" ;
}
);
Skillnaden där är att använda både "asynkrona" återuppringningsmetoder vid slutförande snarare än att bara bygga upp en stack, men också att använda "Bulk Operations API" för att mildra de asynkrona skrivanropen genom att skicka in allt i batchuppdateringssatser på 1000 poster.
Detta bygger inte bara inte upp en stack av funktionsexekvering som din egen exempelkod, utan utför också effektiva "wire"-transaktioner genom att inte skicka allt i individuella uttalanden, utan snarare delas upp i hanterbara "batcher" för serveråtagande .