node.js MongoDB 原子“findOrCreate”:findOne,如果不存在则插入,但不更新
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16358857/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
MongoDB atomic "findOrCreate": findOne, insert if nonexistent, but do not update
提问by Discipol
as the title says, I want to perform a find (one) for a document, by _id, and if doesn't exist, have it created, then whether it was found or was created, have it returned in the callback.
正如标题所说,我想通过_id对文档执行查找(一个),如果不存在,则创建它,然后无论是找到还是创建,都在回调中返回它。
I don't want to update it if it exists, as I've read findAndModify does. I have seen many other questions on Stackoverflow regarding this but again, don't wish to update anything.
如果它存在,我不想更新它,就像我读过 findAndModify 那样。我已经在 Stackoverflow 上看到了很多关于此的其他问题,但同样,不想更新任何内容。
I am unsure if by creating (of not existing), THAT is actually the update everyone is talking about, it's all so confuzzling :(
我不确定通过创建(不存在),这实际上是每个人都在谈论的更新,这一切都令人困惑:(
回答by numbers1311407
Beginning with MongoDB 2.4, it's no longer necessary to rely on a unique index (or any other workaround) for atomic findOrCreatelike operations.
从 MongoDB 2.4 开始,不再需要依赖唯一索引(或任何其他解决方法)来进行findOrCreate类似原子的操作。
This is thanks to the $setOnInsertoperatornew to 2.4, which allows you to specify updates which should only happen when inserting documents.
这是由于在$setOnInsert运营商新的2.4,它允许你指定更新插入文档时应该只发生。
This, combined with the upsertoption, means you can use findAndModifyto achieve an atomic findOrCreate-like operation.
这与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
})
As $setOnInsertonly affects documents being inserted, if an existing document is found, no modification will occur. If no document exists, it will upsert one with the specified _id, then perform the insert only set. In both cases, the document is returned.
由于$setOnInsert只影响插入的文档,如果找到现有文档,则不会发生任何修改。如果不存在文档,它将使用指定的 _id 向上插入一个,然后执行仅插入设置。在这两种情况下,都会返回文档。
回答by hansmaad
Driver Versions > 2
驱动程序版本 > 2
Using the latest driver (> version 2), you'll use findOneAndUpdateas findAndModifywas deprecated. The new method takes 3 arguments, the filter, the updateobject (which contains your default properties, that should be inserted for a new object), and optionswhere you have to specify the upsert operation.
采用最新的驱动程序(> 2版),您将使用findOneAndUpdate作为findAndModify被废弃。这种新方法需要3个参数的filter,该update对象(其中包含您的默认属性,应插入一个新的对象),并options在那里你必须指定更新插入操作。
Using the promise syntax, it looks like this:
使用 promise 语法,它看起来像这样:
const result = await collection.findOneAndUpdate(
{ _id: new ObjectId(id) },
{
$setOnInsert: { foo: "bar" },
},
{
returnOriginal: false,
upsert: true,
}
);
const newOrUpdatedDocument = result.value;
回答by Madarco
Its a bit dirty, but you can just insert it.
它有点脏,但你可以插入它。
Be sure that the key has a unique index on it (if you use the _id it's ok, it's already unique).
确保键上有一个唯一的索引(如果你使用 _id 就可以了,它已经是唯一的了)。
In this way if the element is already present it will return an exception that you can catch.
这样,如果元素已经存在,它将返回一个您可以捕获的异常。
If it isn't present, the new document will be inserted.
如果它不存在,将插入新文档。
Updated:a detailed explanation of this technique on the MongoDB Documentation
更新:MongoDB 文档中对此技术的详细说明
回答by Vidar
Here's what I did (Ruby MongoDB driver):
这是我所做的(Ruby MongoDB 驱动程序):
$db[:tags].update_one({:tag => 'flat'}, {'$set' => {:tag => 'earth' }}, { :upsert => true })}
$db[:tags].update_one({:tag => 'flat'}, {'$set' => {:tag => 'earth' }}, { :upsert => true })}
It will update it if it exists, and insert it if it doesn't.
如果存在,它将更新它,如果不存在则插入它。

