我正在使用最新的node.js本机驱动程序(2.0)批量插入大量文档。
我的集合在URL字段上有一个索引,我必然会从我插入的数千行中获得重复项。有没有办法让MongoDB在遇到重复时不崩溃?
现在我一次批量记录1000个,并使用insertMany。我尝试了各种各样的东西,包括添加{continueOnError = true}。我尝试逐个插入我的记录,但它太慢了,我有成千上万的工作人员排队,并且无法承受延迟。
收藏定义:
self.prods = db.collection('products');
self.prods.ensureIndex({url:1},{unique:true}, function() {});
插入:
MongoProcessor.prototype._batchInsert= function(coll,items){
var self = this;
if(items.length>0){
var batch = [];
var l = items.length;
for (var i = 0; i < 999; i++) {
if(i<l){
batch.push(items.shift());
}
if(i===998){
coll.insertMany(batch, {continueOnError: true},function(err,res){
if(err) console.log(err);
if(res) console.log('Inserted products: '+res.insertedCount+' / '+batch.length);
self._batchInsert(coll,items);
});
}
}
}else{
self._terminate();
}
};
我在考虑在插入之前删除索引,然后使用dropDup重新编制索引,但它似乎有点hacky,我的工作者是聚集的,我不知道如果他们尝试插入记录而另一个进程重新索引会发生什么。 ..有没有人有更好的主意?
修改:
我忘了提一件事。我插入的项目有一个'processed'字段,设置为'false'。但是,数据库中已有的项目可能已被处理,因此该字段可以为“true”。因此我不能upsert ...或者我可以选择一个不被upsert触及的字段?
答案 0 :(得分:2)
2.6 Bulk API正是您所需要的,需要MongoDB 2.6+ * 和节点驱动程序1.4 +。
有两种类型的批量操作:
所以在你的情况下Unordered就是你想要的。上一个链接提供了一个示例:
MongoClient.connect("mongodb://localhost:27017/test", function(err, db) {
// Get the collection
var col = db.collection('batch_write_ordered_ops');
// Initialize the Ordered Batch
var batch = col.initializeUnorderedBulkOp();
// Add some operations to be executed in order
batch.insert({a:1});
batch.find({a:1}).updateOne({$set: {b:1}});
batch.find({a:2}).upsert().updateOne({$set: {b:2}});
batch.insert({a:3});
batch.find({a:3}).remove({a:3});
// Execute the operations
batch.execute(function(err, result) {
console.dir(err);
console.dir(result);
db.close();
});
});
* 文档确实说:“对于比2.6更旧的服务器,API会对操作进行下转换。但是不可能将100%下转换,因此可能会出现轻微的边缘情况无法正确报告正确的数字。“