2015-09-07 148 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

太棒了!谢谢 –

相关问题