$convert 是最通用的强制类型转换操作符,需显式指定 input(带 $ 前缀)和 to(小写准确类型名),建议配置 onError/onNull;$toLong 是其语法糖但仅限 3.6+ 且只支持无损转 long;$toString 更轻量但不支持 array/object。

$convert 是最通用的强制类型转换操作符
它能处理绝大多数字段类型混杂的场景,尤其适合集合中同一字段存在 string / number / date / null 等多种值的情况。关键在于你必须显式指定 input、to 两个必填项,否则聚合会直接报错。
-
input必须是带$前缀的字段引用,比如"$timestamp",不能写成字符串字面量或表达式嵌套(如"$timestamp.toString()") -
to支持的类型名必须小写且拼写准确:"string"、"int"、"long"、"double"、"bool"、"date"、"decimal"—— 写成"String"或"INTEGER"会静默失败或报Invalid type specification -
onError和onNull是可选兜底值,但强烈建议设置,否则遇到无法转换的值(比如"Sunday"转date)会中断整个 pipeline - 示例:把可能为字符串或数字的时间戳统一转为
date:{$project: {cleaned_at: {$convert: {input: "$timestamp", to: "date", onError: null, onNull: null}}}}
$toLong 只适用于整数精度转换,且不兼容早期版本
$toLong 本质是 $convert 的语法糖,等价于 {$convert: {input: ..., to: "long"}},但它更简洁、语义更明确。不过它有硬性限制:只接受能无损转为 64 位有符号整数的输入。
- 支持
int、long、double(小数部分会被截断)、string(仅纯数字字符串如"12345","12.34"或"12abc"会报错) - 不支持
bool(true/false会报错,而$convert默认转成0/1) - MongoDB 3.6+ 才支持
$toLong;如果你用的是 3.4.x(比如 3.4.23),必须改用$convert,否则会提示unknown operator: $toLong - 示例:将用户 ID 字段从 string 强转为 long(假设全为纯数字):
{$project: {user_id_long: {$toLong: "$user_id_str"}}
聚合阶段里用 $toString 比 $convert 更轻量
当目标只是转成字符串,且源字段类型已知为 number / bool / date / null 时,$toString 是更快更安全的选择 —— 它不依赖 onError 配置,也不会因非法输入中断 pipeline。
-
$toString对null返回空字符串"",对缺失字段也返回"";而$convert默认返回null,需靠onNull显式控制 - 不支持直接转 array 或 object,会报
Cannot convert ARRAY to string;此时必须先用$reduce或$map处理子项 - 如果源字段本身是 string,
$toString直接透传,无额外开销;$convert则多一层类型检查 - 示例:把金额字段统一转字符串用于日志拼接:
{$project: {amount_str: {$toString: "$amount"}}
真正要落地,得避开这几个坑
类型转换不是加个操作符就完事,实际跑起来常卡在数据质量或版本兼容上。
- 别在生产集合上直接
bulkWrite改原始字段 —— 先用aggregate+$project验证输出,再用updateMany或bulkWrite回写,否则错一条就丢整批 -
$convert对string→date的解析规则很严格:只认 ISO-8601 格式(如"2023-04-01T12:00:00Z")或毫秒时间戳字符串(如"1587009270000"),"2023/04/01"或"01-Apr-2023"会进onError - 在 MongoDB Atlas 或 Enterprise 中,
$convert支持decimal类型;但 Community Edition 4.4 之前不支持,会报Unrecognized type name: decimal - 如果字段值是嵌套对象(如
{value: 123}),不能直接$convert: "$field"—— 必须先用$getField或点号路径取到叶子值


















