Проблемът тук е, че цикълът, който изпълнявате, не чака завършването на всяка операция. Така че всъщност вие просто подреждате 1000 от .save()
заявки и се опитвате да ги изпълнявате едновременно. Не можете да направите това в рамките на разумни ограничения, поради което получавате отговор за грешка.
async модулът има различни методи за итерация, докато обработва обратно извикване за този итератор, където вероятно най-простият директен за е докато . Mongoose също управлява управлението на връзката вместо вас, без да е необходимо да се вгражда в обратното извикване, тъй като моделите са запознати с връзката:
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
}
);
Не е най-фантастичният начин да го направите, все още се записва едно по едно и бихте могли да използвате други методи за „управление“ на едновременните операции, но това поне няма да взриви стека на повикванията.
Формуляр MongoDB 2.6 и по-висок можете да използвате API за групови операции за да обработва повече от едно писане наведнъж на сървъра. Така че процесът е подобен, но този път можете да изпратите 1000 наведнъж до сървъра с едно писане и отговор, което е много по-бързо:
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
});
}
);
});
Това всъщност използва методите на родния драйвер, които все още не са изложени в mongoose, така че се полагат допълнителни грижи, за да се гарантира, че връзката е налична. Това е пример, но не единственият начин, но основното е, че „магията“ на mongoose за връзки не е вградена тук, така че трябва да сте сигурни, че е установена.
Имате кръгъл брой елементи за обработка, но когато това не е така, трябва да извикате bulk.execute()
в този последен блок, както и показано, но това зависи от числото, отговарящо на модула.
Основната точка е да не нараствате стек от операции до неразумни размери и да поддържате обработката ограничена. Контролът на потока тук позволява операции, чието завършване ще отнеме известно време, преди да преминете към следващата итерация. Така че или пакетните актуализации, или някои допълнителни паралелни опашки са това, което искате за най-добра производителност.
Има и .initializeUnorderedBulkOp()
форма за това, ако не искате грешките при запис да бъдат фатални, но вместо това да ги обработвате по различен начин. Най-често вижте официалната документация за Bulk API и отговорите за това как да интерпретирате дадения отговор.