使用$cond操作符更新无报错但失效,无法切换模型点赞/点踩状态
解决MongoDB点赞/点踩切换的单个查询实现问题
你的Article模型结构:
const articleSchema = new Schema({ name : { type : String, unique: true, required : [true, 'Title is required']}, description : { type : String, required : [true, 'Description is required']}, price : { type : Number, required : [true, 'Price is required']}, category : { type: Schema.Types.ObjectId, ref: 'category', required : [true, 'Not a valid category']}, images : [{type : String}], createdAt : {type: Date, default: () => Date.now()}, creator : { type: Schema.Types.ObjectId, ref: 'users', required : [true, 'This is not a valid user']}, liked : [{ type: Schema.Types.ObjectId, ref: 'users'}], disliked : [{ type: Schema.Types.ObjectId, ref: 'users'}], });
你尝试的几种方案存在的问题:
- 方案1/2:直接在
findOneAndUpdate的更新参数顶层使用$cond或$switch是错误的。MongoDB常规更新语法不支持在顶层放置聚合操作符,只有采用聚合式更新(更新参数传数组)时,才能使用这类聚合操作符。 - 方案4:
$set的字段不能是$cond这类操作符,语法完全错误,因此触发报错。 - 方案5:仅处理了
liked字段,未实现disliked的移除逻辑;且若未添加new: true选项,默认返回更新前的文档,容易误以为操作未生效。
正确实现方案
采用聚合式更新,同时处理liked和disliked两个字段,逻辑如下:
- 检查用户是否在
liked数组内 - 若存在:从
liked中移除用户,disliked保持不变 - 若不存在:将用户加入
liked,同时从disliked中移除用户(如果存在)
代码示例:
const articleQ$ = articles.findOneAndUpdate( { _id: article }, [ { $set: { liked: { $cond: [ { $in: [user, "$liked"] }, { $setDifference: ["$liked", [user]] }, { $concatArrays: ["$liked", [user]] } ] }, disliked: { $cond: [ { $not: { $in: [user, "$liked"] } }, { $setDifference: ["$disliked", [user]] }, "$disliked" ] } } } ], { upsert: true, new: true // 必须添加,返回更新后的文档,默认返回更新前的文档 } ); return articleQ$;
额外注意事项
- 确保
user变量为ObjectId类型,与模型定义一致,不能是字符串,否则$in判断会失效。 - 若你的MongoDB版本低于4.2,不支持聚合式更新,只能拆分两次查询(先查询是否已点赞,再执行对应更新);4.2及以上版本均支持该写法。
内容的提问来源于stack exchange,提问作者Vincent PHILIPPE
相关产品推荐
相关产品推荐

