MongoDB原子“findOrCreate”:findOne,如果不存在则插入,但不更新

时间:2013-05-03 12:23:34

标签: node.js mongodb

正如标题所说,我想通过_id对文档执行查找(一个),如果不存在,则创建它,然后是否已找到或已创建,是否在回调中返回

我不想更新它,如果它存在,因为我读过findAndModify。我在Stackoverflow上看到了很多关于此问题的其他问题,但同样,不希望更新任何内容。

我不确定是否通过创建(不存在),这实际上是每个人都在谈论的更新,这一切都是如此令人困惑:(

4 个答案:

答案 0 :(得分:176)

从MongoDB 2.4开始,不再需要依赖于原始findOrCreate类似操作的唯一索引(或任何其他解决方法)。

这要归功于2.4的the $setOnInsert operator新功能,它允许您指定仅在插入文档时才会发生的更新。

这与upsert选项相结合,意味着您可以使用findAndModify来实现类似原子findOrCreate的操作。

db.collection.findAndModify({
  query: { _id: "some potentially existing id" },
  update: {
    $setOnInsert: { foo: "bar" }
  },
  new: true,   // return new doc if one is upserted
  upsert: true // insert the document if it does not exist
})

由于$setOnInsert仅影响正在插入的文档,如果找到现有文档,则不会进行任何修改。如果不存在任何文档,它将使用指定的_id复制一个文档,然后执行仅插入集。在这两种情况下,都会返回文档。

答案 1 :(得分:6)

它有点脏,但你可以插入它。

确保密钥上有唯一索引(如果使用_id就可以了,它已经是唯一的)。

这样,如果元素已经存在,它将返回一个你可以捕获的异常。

如果不存在,将插入新文档。

已更新: MongoDB Documentation

上有关此技术的详细说明

答案 2 :(得分:4)

使用最新的驱动程序(>版本2),您将findOneAndUpdate使用findAndModify,因为filter已被弃用。新方法需要3个参数,updateoptions对象(包含应为新对象插入的默认属性)和const result = await collection.findOneAndUpdate( { _id: new ObjectId(id) }, { $setOnInsert: { foo: "bar" }, }, { returnOriginal: false, upsert: true, } ); const newOrUpdatedDocument = result.value; ,您必须在其中指定upsert操作。

使用promise语法,它看起来像这样:

Desktop.getDesktop().open(new File("output.txt"));

答案 3 :(得分:1)

这就是我所做的(Ruby MongoDB驱动程序):

$db[:tags].update_one({:tag => 'flat'}, {'$set' => {:tag => 'earth' }}, { :upsert => true })}

如果它存在,它将更新它,如果不存在则将其插入。