我想使用这样的javascript将100万条记录保存到mongodb:
for (var i = 0; i<10000000; i++) {
model = buildModel(i);
db.save(model, function(err, done) {
console.log('cool');
});
}
我试过了,它保存了~160条记录,然后挂了2分钟,然后退出。为什么呢?
答案 0 :(得分:4)
它爆炸了,因为你没有等待异步调用完成,然后再继续下一次迭代。这意味着你正在构建一个&#34;堆栈&#34;未解决的操作直到导致问题。这个网站又叫什么名字?得到照片?
因此,这不是继续进行"Bulk"插入的最佳方式。幸运的是,除了前面提到的回调问题之外,底层MongoDB驱动程序已经考虑过这个问题。实际上有一个"Bulk API"可以使这更好。假设您已将本机驱动程序作为db
对象提取。但我更喜欢使用模型中的.collection
访问器和"async"模块来使一切清晰:
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" ;
}
);
区别在于使用&#34;异步&#34;完成时的回调方法,而不仅仅是构建堆栈,还使用&#34;批量操作API&#34;通过在1000个条目的批量更新语句中提交所有内容来缓解异步写入调用。
这不仅不是&#34;建立一个堆栈&#34;函数执行就像你自己的示例代码一样,但也执行高效的&#34; wire&#34;交易不是通过个人陈述发送所有内容,而是分解成可管理的批次&#34;服务器承诺。
答案 1 :(得分:3)
您应该使用类似Async's eachLimit
的内容:
// Create a array of numbers 0-999999
var models = new Array(1000000);
for (var i = models.length; i >= 0; i--)
models[i] = i;
// Iterate over the array performing a MongoDB save operation for each item
// while never performing more than 20 parallel saves at the same time
async.eachLimit(models, 20, function iterator(model, next){
// Build a model and save it to the DB, call next when finished
db.save(buildModel(model), next);
}, function done(err, results){
if (err) { // When an error has occurred while trying to save any model to the DB
console.error(err);
} else { // When all 1,000,000 models have been saved to the DB
console.log('Successfully saved ' + results.length + ' models to MongoDB.');
}
});