插入记录而不会导致重复

时间:2014-10-31 06:23:01

标签: node.js mongodb

我正在使用最新的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触及的字段?

1 个答案:

答案 0 :(得分:2)

2.6 Bulk API正是您所需要的,需要MongoDB 2.6+ * 和节点驱动程序1.4 +。

有两种类型的批量操作:

  1. 订购批量操作。这些操作按顺序执行所有操作,并在第一次写入错误时执行错误。
  2. 无序批量操作。这些操作并行执行所有操作并聚合所有错误。无序批量操作不保证执行顺序。
  3. 所以在你的情况下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%下转换,因此可能会出现轻微的边缘情况无法正确报告正确的数字。