$convert 不设 onerror/onnull 会中断管道,因 mongodb 默认“硬失败”:类型转换异常(如"abc"转int)直接抛错终止;onerror捕获转换失败,onnull仅响应null/缺失字段,二者须显式、驼峰、正确赋值。

$convert 的 onError 和 onNull 必须显式设置,否则类型转换失败会直接中断整个聚合管道。
为什么 $convert 不加 onError/onNull 就报错?
MongoDB 默认对类型转换失败采取“硬失败”策略:比如把 "abc" 强转 int,或把 "2024-02-xx" 转 Date,驱动不会默默跳过或设为 null,而是抛出 MongoServerError: Conversion failed 并终止管道执行。
-
onError仅响应“转换过程失败”,例如字符串格式非法、溢出、时区解析失败等 -
onNull只响应输入字段本身为null或完全缺失($$REMOVE后的状态) - 二者互不覆盖,必须同时显式声明,哪怕都设成
null
onError/onNull 填什么才有效?
这两个键名严格区分大小写和驼峰,拼错(如 on_error、onerror)会导致参数被静默忽略。
- 合法值只能是字面量或表达式:
null、0、"invalid"、$$REMOVE - 别写
onError: "ignore"—— MongoDB 不识别这个字符串,报错提示类似unknown operator: onError - 在 Node.js 驱动中,确保传入的是标准 JS 对象:
{ $convert: { input: "$price", to: "int", onError: null, onNull: null } } - 用
console.log(JSON.stringify(pipeline))或开启驱动 debug 日志,确认 BSON 请求体里真有这两个键
为什么 $convert 放在 $group 里没反应?
$convert 在 $sum、$avg 等累加器内部不生效 —— 这些阶段会在聚合早期就尝试求值,错误直接上抛,根本没机会触发 onError。
- 正确做法:用
$set或$addFields提前转换字段类型,再进$group - 若必须在
$group内部处理,改用$cond+$isNumber/$type手动判断,例如:{ $cond: [{ $isNumber: "$price" }, "$price", 0] } -
$convert对ObjectId、Binary等特殊类型支持有限;转string安全,转int很可能失败且onError也兜不住
类型不一致导致的隐性失败怎么查?
聚合里最隐蔽的失败不是语法错,而是字段类型错位:比如一个集合存的是字符串 "123",另一个存的是数字 123,$lookup 或 $match 会静默不匹配。
- 先用
db.collection.findOne().yourField手动确认两边字段的真实类型 - 在聚合开头加
{ $match: { yourField: { $type: "string" } } }或"double"过滤异常类型 - 对数组内嵌
_id匹配,必须用ObjectId("...")构造,不能直接比字符串 —— 隐式转换在嵌套结构里大概率失效
真正容易被忽略的,是 onNull 和 onError 的触发边界:输入是 null 值 ≠ 输入字段缺失;上游已设 "field": null,$convert 的 onNull 就不会触发 —— 这时候得靠 onError 或前置 $ifNull 拦截。











