2015-09-07 70 views
8

是否可以在條件中插入Mongo;MongoDB-如果不存在則插入,否則跳過

//Pseudo code 

Bulk Insert Item : 

If Key exists 
    Skip, don't throw error 
If key does not exist 
    Add item 

,如果我做一個插入,它可能會返回一個錯誤或集合中插入,但有可能在散裝

+0

閱讀[「UPSERT」](HTTP://docs.mongodb。組織/手動/參考/方法/ db.collection.update /#UPSERT選項)。因爲MongoDB是這樣做的。有'.upsert()'作爲批量操作所需的修飾符。另外['$ setOnInsert'](http://docs.mongodb.org/manual/reference/operator/update/setOnInsert/)只會在新文檔被「插入」時應用更改,否則不會執行任何操作,如果唯一操作在該塊。 –

回答

12

你有兩個真正的選擇這裏取決於你想如何處理事情:

  1. 使用upsert的MongoDB的功能是否存在的關鍵數據基本上是「查找」。如果不是,那麼你只能傳遞數據到$setOnInsert,這不會觸及其他任何東西。

  2. 批量使用「UnOrdered」操作。即使返回錯誤,整批更新也會繼續,但錯誤報告就是這樣,並且任何不是錯誤的都將被排除。

整體例如:

var async = require('async'), 
    mongoose = require('mongoose'), 
    Schema = mongoose.Schema; 

var testSchema = new Schema({ 
    "_id": Number, 
    "name": String 
},{ "_id": false }); 

var Test = mongoose.model('Test',testSchema,'test'); 

mongoose.connect('mongodb://localhost/test'); 

var data = [ 
    { "_id": 1, "name": "One" }, 
    { "_id": 1, "name": "Another" }, 
    { "_id": 2, "name": "Two" } 
]; 

async.series(
    [ 
    // Start fresh 
    function(callback) { 
     Test.remove({},callback); 
    }, 

    // Ordered will fail on error. Upserts never fail! 
    function(callback) { 
     var bulk = Test.collection.initializeOrderedBulkOp(); 
     data.forEach(function(item) { 
     bulk.find({ "_id": item._id }).upsert().updateOne({ 
      "$setOnInsert": { "name": item.name } 
     }); 
     }); 
     bulk.execute(callback); 
    }, 

    // All as expected 
    function(callback) { 
     Test.find().exec(function(err,docs) { 
     console.log(docs) 
     callback(err); 
     }); 
    }, 


    // Start again 
    function(callback) { 
     Test.remove({},callback); 
    }, 

    // Unordered will just continue on error and record an error 
    function(callback) { 
     var bulk = Test.collection.initializeUnorderedBulkOp(); 
     data.forEach(function(item) { 
     bulk.insert(item); 
     }); 
     bulk.execute(function(err,result) { 
     callback(); // so what! Could not care about errors 
     }); 
    }, 


    // Still processed the whole batch 
    function(callback) { 
     Test.find().exec(function(err,docs) { 
     console.log(docs) 
     callback(err); 
     }); 
    } 
    ], 
    function(err) { 
    if (err) throw err; 
    mongoose.disconnect(); 
    } 
); 

注意「改變行爲」,在當前的驅動程序是在.execute()結果響應將返回一個錯誤對象被拋出,在以前的版本中沒有通過「無序」操作執行此操作。

這就要求您的代碼永遠不要依賴於單獨返回的err,並且您應該輸入返回的result而不是錯誤的完整分類。

儘管如此,當無序時,無論發生多少錯誤,批處理都會一直持續到結束。沒有錯誤的事情將如常進行。

這真的歸結爲「序列重要」。如果是這樣,那麼你需要「有序」操作,你只能通過使用「upserts」來避免重複的鍵。否則使用「無序」,但要注意錯誤返回以及它們實際上的含義。

此外,當使用.collection從基礎驅動程序獲取底層集合對象以啓用「批量」操作時,請始終確保首先調用「某種」貓鼬方法。

如果沒有這種方法,那麼與本機驅動程序方法沒有保證的數據庫連接,因爲它是爲mongoose方法處理的,所以操作將因沒有連接而失敗。

交替爲「擊發」貓鼬方法首先,是包裝應用程式邏輯中的事件偵聽器的連接:

mongoose.connection.on("open",function(err) { 
    // app logic in here 
}) 
+1

太棒了!謝謝 –

相關問題