javascript - MongoDB - 检查 $addToSet 是否重复
问题描述
我正在使用 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);
});
它能做什么:
- 如果集合中没有文档,则创建一个并填写所有字段
- 如果存在文档,则仅更新
likes
具有新用户 ID 的数组
这可以按预期工作并且没有问题,这要归功于$addToSe
我没有任何重复等。
然而,在上面的代码被执行并result
返回之后,我需要做一些额外的事情,为了让它工作,我需要知道 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
在更新之前比较数组是否包含用户 ID 和 javascriptincludes
方法。
有更好的想法吗?
解决方案
我找到了解决方案!
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);
});
});
}
希望这个答案能帮助将来遇到类似问题的人:)
推荐阅读
- ios - 如何在 PWA (React) 中访问 ios 中的摄像头和耳机
- css - 旋转
不在其位置旋转 - html - 如何使用 R 将文本文件超链接到 HTML 文件中?
- jupyter-notebook - CPlex Optimization Studio 12.9.0 是否与用于 API 的 Python 笔记本兼容。如果是,哪个版本的 Python?
- python - 为 csv 中的列创建不同的元组值并计算第三列的平均值
- azure - 页面重新加载/导航到另一个页面后,有没有办法在 MS Bot Framework 网络聊天中保留聊天历史记录?
- ios - 取消自定义视图控制器转换后执行解除完成回调
- geolocation - Adobe Analytics 如何通过 Tealium 收集地理位置变量(城市或国家/地区)?
- c - blk_get_request 在未分区的块设备上使用时崩溃
- javascript - DataTables 条件格式栏