2014-10-31 147 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