最常见的错误是把$cond当成javascript三元操作符写成{$cond:[条件,真值,假值]},这在旧版mongodb中会报错“$cond requires 3 arguments”,因旧版仅支持{$cond:{if:,then:,else:}}语法。

为什么 $cond 返回 null 或报错“$cond requires 3 arguments”
最常见的错误是把 $cond 当成 JavaScript 三元操作符写成 { $cond: [条件, 真值, 假值] } —— 这在旧版 MongoDB({ $cond: { if: ..., then: ..., else: ... } }。漏掉任意一个字段、拼错字段名(比如写成 elif 或 otherwise),都会直接报错或静默返回 null。
实操建议:
- 永远用对象形式,别用数组形式(即使文档里还写着“legacy syntax”也别碰)
-
if必须是布尔表达式,不能是字符串或数字;用$eq、$gt等显式比较,别依赖隐式转换 -
then和else的返回类型最好保持一致(比如都是字符串或都是数字),否则下游$group或$sort可能行为异常 - 嵌套
$cond时,外层else里再写一个$cond是完全合法的,但建议提取成变量或拆到单独$addFields阶段,避免可读性崩塌
在 $project 中用 $cond 分类字段值(比如 status → “active”/“inactive”)
这是最典型的使用场景:把原始数值或布尔字段映射为语义化标签。关键点在于,$cond 本身不改变字段结构,它只是计算一个新值,所以必须配合 $project 或 $addFields 使用。
示例:把 is_active: true/false 转成 status: "active"/"inactive"
{
$project: {
status: {
$cond: {
if: { $eq: ["$is_active", true] },
then: "active",
else: "inactive"
}
}
}
}
注意:
-
"$is_active"的引号不能少,否则 MongoDB 当作字面量字符串is_active而不是字段引用 - 如果
is_active可能为null或缺失,$eq会返回false,导致归入else分支;需要更严谨判断时改用$and: [{ $ne: ["$is_active", null] }, { $eq: ["$is_active", true] }] - 不要在
$match阶段用$cond做过滤——它不返回布尔值,无法用于匹配;该用$expr+$eq等操作符
在 $group 中用 $cond 统计条件计数(比如 count active users)
想按条件聚合计数?别写循环或多次 $group。直接在 $sum 里嵌套 $cond:让满足条件时加 1,否则加 0。
示例:统计每个部门中 active 用户数和 total 用户数
{
$group: {
_id: "$department",
active_count: {
$sum: {
$cond: { if: { $eq: ["$is_active", true] }, then: 1, else: 0 }
}
},
total_count: { $sum: 1 }
}
}
性能提示:
- 这种写法比先
$match再$group多次更高效,因为只遍历一次数据 - 如果条件复杂(比如多字段联合判断),把
if表达式提前放到$addFields阶段生成临时布尔字段,再在$group里引用,可提升可读性和调试效率 - 注意
$sum的输入必须是数字;then: "1"(字符串)会导致整个聚合失败
用 $cond 处理缺失字段或 null 值(避免 undefined 行为)
MongoDB 对缺失字段和 null 的处理很严格:"$missing_field" 在布尔上下文中是 false,但直接参与 $eq 比较可能不符合预期。稳妥做法是显式检查存在性和非空性。
示例:给没有 score 的用户设默认值 0,有则保留原值
{
$addFields: {
safe_score: {
$cond: {
if: { $or: [{ $eq: ["$score", null] }, { $not: "$score" }] },
then: 0,
else: "$score"
}
}
}
}
说明:
-
{ $not: "$score" }同时覆盖字段缺失和值为false/0/""的情况;如果只想捕获缺失和null,改用{ $eq: [{ $type: "$score" }, "missing"] }或{ $eq: ["$score", null] } - 别用
$ifNull替代——它只能处理null和缺失,不能做条件分支;而$cond更通用,适合复合逻辑 - 在索引字段上用
$cond不影响查询性能,但它本身不触发索引;真正影响性能的是if表达式里是否用了可索引字段和操作符(如$eq、$in)
$cond 的 if 表达式里所有字段引用都必须带 $ 前缀,且不能跨层级访问嵌套对象里的字段而不加路径(比如 "$profile.age" 不能简写成 "$age")。一旦字段路径写错,结果就是静默的 null,很难排查。











