我尝试了数十种解决方案,但没有一个有效,而且大多数都已被弃用。
我有一个包含如下文档的集合:
_id: 5d99ef3285c93711828cd15d
code: 1234
name: "Foo"
surname: "Bar"
address: "That street"
phone: 1234567
仅当没有任何具有相同代码
的文档时,我才想插入新文档。
我最后一次尝试是这样的:
const result = await db.collection('users').findOneAndUpdate(
{ code: user.code },
{
$setOnInsert: user,
},
{
upsert: true,
}
);
但我得到E11000重复键错误集合...
updateOne()
返回相同的错误; update()
已弃用...
那么,如何仅添加新文档并获取结果(如果已添加文档则为 true,如果文档已存在则为 false)?
谢谢。
最佳答案
据我所知,
使用 $set 和 $setOnInsert,我们可以不更新/插入相同的字段。
即$set 和 $setOnInsert 应该是互斥的。
如果正在更新文档,它会起作用,但如果正在插入文档,则会抛出异常。
如果更新,$setOnInsert 将被忽略。
如果插入,两者都会被执行。
我认为解决方案是,
使用 returnNewDocument 并在架构中有一个字段 isUpdated
默认为 false。
Note:
make sure whenever you use "insert" operation on the collection, you don't add
isUpdated
which will be set to false then or set it to false.
形成一个查询,例如
db.collection('users').findOneAndUpdate(
{ code: user.code },
{
$set: user, // which has user.isUpdated set to true
},
{
upsert: true,
returnNewDocument: false, // (by default it is false only)
}
);
按照这个逻辑,
所以让我们一步一步来
如果文档
doc1
不存在,它将被插入,并且mongo将返回响应null
。你会知道,它是已插入。如果文档 doc2 存在(考虑到此逻辑不适用于之前插入的文档
doc2
且 doc2 中不存在isUpdated
字段),它将执行$set,因此在返回的游标中,该字段不存在,即未定义
,因此您可以从中知道,它已更新。假设我们再次对
doc1
发出相同的查询(该查询存在并且我们已经应用了新逻辑),那么有两种情况a.它将被更新,并且在游标中,我们的
isUpdated
等于 false。b.它将被更新,并且在游标中,我们的
isUpdated
等于 true。在这两种情况下,您都知道它已更新
我认为这种方法应该可以解决您的问题。
如果这对您有帮助,或者您找到任何其他解决方案,请分享。
更新
实际上
您甚至不需要另一个字段isUpdated
,没有这个字段,这应该使用相同的逻辑。
即如果光标为空,则插入,如果不为空,则更新。
关于javascript - Mongodb 版本 3+ : how to insert new document only if it doesn't exist and get the result,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58258301/