如何用Mongoose实现字段不存在设为true、存在则取反的单请求更新
实现MongoDB布尔字段的状态切换(含字段不存在时的默认值)
可以通过MongoDB的聚合管道操作符实现单请求更新,同时覆盖字段不存在和存在的场景:
修改后的代码
let updateUser = await User.findByIdAndUpdate(user_id, [ { $set: { is_blacklisted: { $cond: [ { $exists: ["$is_blacklisted"] }, // 判断字段是否存在 { $not: ["$is_blacklisted"] }, // 存在则取反现有值 true // 不存在则设为true ] } } } ], { new: true }); // 可选:添加new:true返回更新后的文档,方便验证结果
原代码问题分析
原代码使用$eq: [false, "$is_blacklisted"]处理值切换,但当字段不存在时,"$is_blacklisted"会被解析为null,$eq: [false, null]的计算结果为false,导致最终将is_blacklisted设为false,不符合“字段不存在时设为true”的需求。
方案说明
- 使用
$cond条件操作符分支处理两种场景:- 通过
$exists精准判断is_blacklisted字段是否存在 - 字段存在时,用
$not对现有值取反(布尔值直接取反,非布尔值会按MongoDB布尔规则转换后取反) - 字段不存在时,直接设置为
true
- 通过
更简洁的替代写法
如果追求代码简洁,也可以用$ifNull实现相同逻辑:
let updateUser = await User.findByIdAndUpdate(user_id, [ { $set: { is_blacklisted: { $ifNull: [ { $not: ["$is_blacklisted"] }, true ] } } } ], { new: true });
原理:当字段存在时,返回$not取反后的结果;当字段不存在时,$is_blacklisted为null,$ifNull会返回预设的true。
内容的提问来源于stack exchange,提问作者LeMecWeird
相关产品推荐
相关产品推荐

