2014-10-31 94 views
1

我用最新的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(); 
    } 
}; 

我想插入之前删除索引,然后使用dropDups重建索引,但它似乎有点哈克,我的工人都聚集我不知道如果他们尝试插入记录而另一个进程是重新索引时会发生什么......有没有人有更好的主意?

编辑:

我忘了提一两件事。我插入的项目有一个'已处理'字段,它被设置为'假'。但是,已经在db中的项目可能已经被处理了,所以这个域可以是'true'。因此,我不能插手......或者我可以选择一个未被upsert修改的字段?

+0

我认为你正在寻找批量upserts。 – 2014-10-31 06:58:39

+0

我的问题是,我不能插入,已经在集合中的项目有一个字段'已处理',可以是真或假,而我插入的字段将始终为'假' – xShirase 2014-10-31 11:18:54

回答

2

2.6 Bulk API是你正在寻找的,这将需要MongoDB 2.6+ *和节点驱动程序1.4+。

有2种类型的批量操作的:

  1. 有序批量操作。这些操作按顺序执行所有操作,并在第一次写入错误时出错。
  2. 无序批量操作。这些操作并行执行所有操作并聚合所有错误。无序批量操作不保证执行顺序。

所以在你的情况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%,因此有可能是轻微的边缘情况下,它不能正确报告正确的数字。

+0

有趣,尤其是错误的汇总。我会试试看,谢谢!性能如何?我平均每次插入10k条记录。 – xShirase 2014-10-31 11:23:29

+0

它的性能可能与您之前进行批次的方式类似。最佳批量大小取决于文档大小和特定环境,所以我建议您尝试一下。可以是每批从100到5000的任何地方。 – helmy 2014-10-31 17:53:34

+0

奇妙地做了这个技巧!我还没有玩过批量大小,没有真正的需要,我插入任何地方从100到35K记录没有任何问题或明显放缓。快速的问题不值得打开一个新的线程,你知道err和res对象的文档在哪里吗?我无法在任何地方找到它... – xShirase 2014-11-02 01:37:59