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

正如标题所说,我希望通过 _ id 为文档执行 find (one) ,如果不存在,就创建它,然后不管它是被发现还是被创建,都在回调中返回它。

如果它存在,我不想更新它,因为我已经阅读了 findAndAmendment。我已经看到了许多其他问题关于 Stackoverflow 这一点,但再次,不希望更新任何东西。

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

74175 次浏览

有点脏,不过你可以直接插进去。

确保键具有唯一的索引(如果使用 _ id,则没问题,它已经是唯一的)。

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

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

更新: < a href = “ http://docs.MongoDB.org/Manual/lessons/”rel = “ nofollow”> MongoDB 文件上對這種技術的一個細節解釋

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

这要感谢 $setOnInsert操作员 new to 2.4,它允许您指定只在插入文档时才会发生的更新。

这与 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 插入一个文档,然后执行只插入集。在这两种情况下,都会返回文档。

下面是我所做的(Ruby MongoDB 驱动程序) :

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

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

驱动程序版本 > 2

使用最新的驱动程序(> 版本2) ,您将使用 FindOneAndUpdate,因为不推荐使用 findAndModify。新方法有3个参数: filterupdate对象(其中包含应该为新对象插入的默认属性)和 options,其中必须指定 upsert 操作。

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

const result = await collection.findOneAndUpdate(
{ _id: new ObjectId(id) },
{
$setOnInsert: { foo: "bar" },
},
{
returnOriginal: false,
upsert: true,
}
);


const newOrUpdatedDocument = result.value;