$round在聚合中不生效因版本低于4.2、未嵌套于$project/$addfields/$set阶段,或输入非数字;保留2位小数用{ $round: ["$price", 2] },结果为double类型。

为什么 $round 在聚合管道里不生效?
因为 $round 是 MongoDB 4.2+ 才支持的聚合操作符,低于这个版本会直接报错 "$round" is not a valid expression operator。另外,它不能单独用在 $project 外的阶段(比如 $match 或 $sort),也不能作用于非数值字段——如果字段是字符串或 null,结果会是 null。
- 确认 MongoDB 版本:运行
db.version(),必须 ≥ 4.2 - 确保输入是数字类型:可用
$toDouble或$convert预处理 -
$round必须嵌套在$project、$addFields或$set中使用
怎么用 $round 保留 2 位小数?
$round 接收两个参数:[<em>number</em>, <em>place</em>],第二个参数是保留的小数位数(可正可负)。保留 2 位就是写 2;注意不是四舍五入到百分位,而是真正截断到小数点后两位的 IEEE 754 四舍五入行为。
{
$project: {
price_rounded: { $round: ["$price", 2] }
}
}
- 如果
$price是19.888,结果是19.89 - 如果
$price是19.884,结果是19.88 - 如果字段缺失或为
null,$round返回null,不会报错
想保留 0 位小数但避免整型转换失败?
直接写 { $round: ["$value", 0] } 没问题,但要注意:MongoDB 的 NumberInt/NumberLong 和 double 在聚合中会统一为 double,所以结果仍是双精度浮点数(如 42.0),不是整型。如果下游应用强依赖整型,得额外用 $toInt 转换,但要小心溢出和精度丢失。
- 安全做法:
{ $toInt: { $round: ["$value", 0] } } - 但若
$value是9223372036854775807.5这类超大数,$toInt会返回null - 更健壮的写法是加
$cond判断范围,或接受 double 类型输出
常见错误:$round 套在 $sum 里结果不对?
典型场景是先 $sum 再 $round,但写成 { $round: [{ $sum: "$amount" }, 2] } 是对的;错的是把 $round 放在 $sum 内部,比如 { $sum: { $round: ["$amount", 2] } }——这会先对每个文档的 $amount 单独四舍五入,再求和,和先求和再四舍五入结果可能不同(尤其数据量大、小数位多时)。
- 先加总再取整(推荐):
{ $round: [{ $sum: "$amount" }, 2] } - 先单条取整再加总(有偏差):
{ $sum: { $round: ["$amount", 2] } } - 性能上没区别,但语义和数值结果差异明显,容易被忽略
$round 行为严格遵循 IEEE 754,不提供“向上取整”或“截断”模式;需要这些功能得组合 $ceil、$floor 或乘除移位模拟。











