mongoose updateOne 功能:如果 $pull 不起作用则不更新
Posted
技术标签:
【中文标题】mongoose updateOne 功能:如果 $pull 不起作用则不更新【英文标题】:mongoose updateOne function: don't update if $pull didn't work 【发布时间】:2020-12-01 02:14:06 【问题描述】:我正在使用这样的updateOne
方法:
Photo.updateOne(
"_id": photoId
,
"$pull":
comments:
_id: ObjectID(commentId),
"user.id": user.id
,
"$inc": "commentCount": -1 ,
,
)
Photo
包含 cmets 作为数组和 commentCount
作为数字的模型。当我运行代码时,它正在工作,但如果照片没有评论(我试图拉)它仍然将commentCount
增加-1
。我想要的是,如果代码没有在照片 cmets 中提取任何评论,也不要更新 commentCount
。如何将此规则添加到我的代码中?
感谢您的帮助。
【问题讨论】:
我已经更新了我的答案,在查询部分添加了$elemMatch
,以确保 cmets 上的两个字段相等,然后进入更新部分,在极少数情况下会发生这种情况,否则我的旧条件也将起作用,因为您正在更新单个文档并几乎使用 _id 字段,它对于特定的父文档来说是唯一的。
它工作得很好。感谢您的帮助
【参考方案1】:
您也可以在查询部分同时添加comments._id
和comments.use.id
条件,如果评论不可用则跳过更新和拉取部分。
Photo.updateOne(
_id: photoId,
comments:
$elemMatch:
_id: ObjectID(commentId),
"user.id": user.id
,
"$pull":
comments:
_id: ObjectID(commentId),
"user.id": user.id
,
"$inc": "commentCount": -1
)
【讨论】:
您需要 elemMatch 以确保comments._id
和 comments.user.id
满足相同的评论。
@Joe 感谢您的建议,我已经在没有$elemMatch
它的情况下进行了测试,它工作得很好。如果您说要在查询部分中使用,那么默认情况下更新是使用.
点提供数组匹配,则无需使用该运算符,如果您说要在更新(拉)部分中使用,那么它将不起作用,因为$elemMatch 只是查询和投影运算符。
我的意思是,如果 cmets 数组中的一个元素与"comments._id": ObjectID(commentId)
匹配,而另一个元素与"comments.user.id": user.id
匹配,它将满足您在此处显示的查询部分,但$pull
不会在$inc
修改计数时删除任何内容。在查询部分使用$elemMatch
可以防止这种情况发生。【参考方案2】:
Mongo 中不存在这样的功能,如果您使用 Mongo v4.2+,您可以使用pipelined update,顾名思义,这使您能够在更新中使用管道,因此允许我们根据之前的结果来获得条件。
Photo.updateOne(
"_id": photoId ,
[
$set:
comments:
$filter:
input: "$comments",
as: "comment",
cond:
$and: [
$ne: ["$$comment._id", ObjectID(commentId)],
$ne: ["$$comment.user.id", user.id] //really necessary?
]
,
$set:
commentCount: $size: "$comments"
]
)
对于较小的版本,您必须将其拆分为 2 个调用。没办法。
------------- 编辑 ----------------
您可以使用$elemMatch 更新查询以查找文档,如果找不到,则表示该评论属于其他人,在这种情况下您可以抛出错误。
Photo.updateOne(
_id: photoId,
comments:
$elemMatch:
_id: objectID(commentId),
"user.id": user.id
,
"$pull":
comments:
_id: ObjectID(commentId),
"user.id": user.id
,
"$inc": "commentCount": -1
)
【讨论】:
感谢您的回答,但效果不佳。我正在尝试这样做,因为如果用户尝试删除其他人的评论,我想返回一条错误消息。在您的代码中,如果用户尝试删除其他用户的评论,这将起作用,因为条件错误。假设我们有 2 个不同的评论,例如 userId:1,commentId:1, userId:2,commentId:2 如果一个 id 值等于 3 的用户尝试删除 commentId=1 这将成功,因为您的代码检查条件 commentId != 1 && userId != 3,这将只返回第二条评论。 您可以检查modifiedCount
以查看文档是否已更改,然后抛出错误。既然我了解了您的需求,请使用$elemMatch
在一个简化的示例中添加以上是关于mongoose updateOne 功能:如果 $pull 不起作用则不更新的主要内容,如果未能解决你的问题,请参考以下文章
updateOne $ set not working - Mongoose
TypeScript 中的 Mongoose post hook 类型错误
UpdateOne MongoDB 使用来自另一个字段的值进行推送