我正在使用 MongoDB 为我的应用程序创建类似的功能。我最近偶然发现一个问题。
我喜欢的代码:
async function like(articleId, userId) {
const db = await makeDb();
return new Promise((resolve, reject) => {
const result = db.collection(collectionName).findOneAndUpdate(
{ articleId: ObjectID(articleId) },
{
$setOnInsert: {
articleId: ObjectID(articleId),
creationDate: new Date()
},
$addToSet: { likes: ObjectID(userId) }
},
{ upsert: true }
);
resolve(result);
});
它的作用:
- 如果集合中没有文档,请创建一个文档并填写所有字段
- 如果文档存在,仅使用新的用户 ID 更新
likes
数组
这按预期工作,没有任何问题,感谢 $addToSe
t 我没有任何重复项等。
但是,在执行上述代码并返回结果
之后,我需要做一些额外的事情,为了让它工作,我需要知道 Mongos $addToSet
是否做了改变任何东西。
简而言之:
- 如果新的 userId 已添加到
likes
数组中,我想做点什么 - 如果 userId 已在
likes
数组中,并且$addToSet
没有更改任何内容,我不想采取任何操作。
有没有办法区分$addToSet
是否做了什么?
结果的当前 console.log()
如下所示:
{
lastErrorObject: { n: 1, updatedExisting: true },
value: { _id: 5e2c47c57bb5183d80dce14f,
articleId: 5da4d1365217baf52fbcd76a,
creationDate: 2020-01-25T13:51:01.928Z,
likes: [ 5d750b677d8edfc08af8a527 ]
},
ok: 1
}
我想到的一件事(但在性能方面非常糟糕)是在更新之前比较 likes
数组是否包含 userID 与 javascript includes
方法。
还有更好的想法吗?
最佳答案
我找到了解决方案!
这个答案的 99% 归功于 Neil Lunn
:
https://stackoverflow.com/a/44994382/2175228
它让我走上了正轨。我放弃了 findOneAndUpdate
方法,转而使用 updateOne
方法。查询参数等一切都保持不变,只是方法名称发生了变化,显然该方法的结果类型也发生了变化。
updateOne
方法的问题是它不返回已更新的对象(或旧的对象)。但它确实返回了upsertedId,这是我的情况下唯一需要的。
所以最终你得到的是一个非常长的 CommandResult
对象,其开头为:
CommandResult {
result: { n: 1, nModified: 0, ok: 1 },
(...)
}
但是当我仔细观察时,我注意到该对象恰好具有我一直需要的那些字段:
modifiedCount: 0,
upsertedId: null, // if object was inserted, this field will contain it's ID
upsertedCount: 0,
matchedCount: 1
所以您需要做的就是从 CommandResult
对象中获取您需要的部分,然后继续;)
更改后我的代码:
async function like(articleId, userId) {
const db = await makeDb();
return new Promise((resolve, reject) => {
db.collection(collectionName)
.updateOne(
{ articleId: ObjectID(articleId) },
{
$setOnInsert: {
articleId: ObjectID(articleId),
creationDate: new Date()
},
$addToSet: { likes: ObjectID(userId) }
},
{ upsert: true }
)
.then(data => {
// wrap the content that You need
const result = {
upsertedId: data.upsertedId,
upsertedCount: data.upsertedCount,
modifiedCount: data.modifiedCount
};
resolve(result);
});
});
}
希望这个答案能够帮助将来遇到类似问题的人:)
关于javascript - MongoDB - 检查 $addToSet 是否重复,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59910077/