$switch 是 MongoDB 5.0+ 中替代嵌套 $cond 的更清晰方案,但需显式定义 default,否则未匹配时返回 null;仅支持离散值严格匹配,不适用于范围判断;switch 表达式须返回标量,case 必须为字面量或单值表达式,default 不可省略。

直接说结论:$switch 在 MongoDB 5.0+ 中是替代嵌套 $cond 的更清晰方案,但它不自动 fallback,每个分支必须显式覆盖所有可能输入,漏写 default 就会返回 null —— 这是线上逻辑错乱的高发点。
为什么不用嵌套 $cond 而选 $switch
当业务规则超过 3 个分支(比如按用户等级给不同折扣),嵌套 $cond 会迅速变成“右括号地狱”:一个 else 套一个 else,调试时数括号都费劲。而 $switch 把条件平铺,结构一目了然,且支持 branches 数组 + default 统一兜底。
但注意:$switch 是严格匹配,不是“范围判断”。它只适合离散值分支(如 status 字段为 "draft" / "published" / "archived"),不适合 $gte 类连续区间逻辑——那种场景还得回退到 $cond。
动态切换AI模型以优化成本与性能。当用户发出“eco mode”、“balanced mode”、“smart mode”或“max mode”等模式指令,或使用“/modes status”查询状态及“/modes setup”配置模式时触发。
$switch 的三个硬性要求
实际写的时候,这三处最容易漏或写错:
-
switch表达式必须返回标量值(不能是对象或数组),否则整个$switch返回 null;常见坑是写了"switch": "$user.profile",结果 profile 是个对象,匹配失败 -
branches里每个case必须是字面量或单值表达式(如"case": "vip"或"case": {"$toString": "$level"}),不支持{"$in": ["a", "b"]}这种复合条件 -
default不是可选的——即使你认为“所有 case 都覆盖了”,MongoDB 仍可能因字段缺失、类型不符(比如期望字符串却遇到 null)而掉进 default;没写default就等于让该字段变 null
多语言 fallback 这类链式逻辑怎么写
比如用户 locale 是 "zh-Hans",但文档只存了 "zh" 和 "en",想自动降级到 "zh" 再 fallback 到 "en" —— $switch 本身不支持链式匹配,得靠嵌套或预处理:
- 方案一:用
$switch匹配最精确的 locale,再在外层用$cond判断结果是否为空,为空则重试次优 locale(比如先查"zh-Hans",空则查"zh") - 方案二:在应用层做 fallback,数据库只存基础字段(如
title: { zh: "...", en: "..." }),把降级逻辑留在代码里,避免聚合管道膨胀 - 方案三:用
$let+$switch预计算 fallback 链,但要注意$switch的case顺序就是匹配优先级,必须从最细粒度写到最粗粒度("zh-Hans"→"zh"→"en")
真正麻烦的从来不是语法,而是字段存在性、类型混杂、以及 fallback 时要不要保留原始字段名——这些细节不提前约定好,聚合阶段越写越不敢动。

















