$mul是最直接的翻倍方式,但要求字段为数值类型,非数字类型(如字符串、布尔值、null)会报错;字段不存在时自动设为0;支持多字段及嵌套字段翻倍,但不支持数组内字段直接点号操作;需注意精度、并发性能与版本兼容性。

$mul 是最直接的翻倍方式,但必须确保字段是数值类型,且要留意字段不存在时自动设为 0 的行为。
字段必须是数字,否则会报错
如果目标字段不是数值(比如是字符串 "100"、布尔值或 null),$mul 会直接失败,抛出类似 Cannot apply $mul to non-numeric field 的错误。
- 先用
find()检查字段类型:db.collection.find({ price: { $type: "string" } }) - 批量修复非数字字段可配合
$set+ 聚合表达式(MongoDB 4.2+):{ $set: { price: { $convert: { input: "$price", to: "decimal", onError: 0 } } } } - 字符串转数字后,再执行
$mul,避免中断整个更新流程
翻倍操作写法与常见陷阱
翻倍就是乘以 2,但要注意写法细节和隐式类型转换:
- 正确写法:
{ $mul: { price: 2 } }(整数翻倍)、{ $mul: { price: 2.0 } }(强制 double) - 如果原字段是
Decimal128,建议也用Decimal128("2")避免精度丢失 - 错误写法:
{ $mul: { price: "2" } }→ 报错:乘数必须是数值,不能是字符串 - 字段不存在时,
$mul会新建该字段并设为0(不是2),这点和$inc不同
批量翻倍多个字段或嵌套字段
支持一次更新多个字段,点号路径也能生效:
- 同级字段:
{ $mul: { price: 2, quantity: 2, discount: -1 } } - 嵌套字段:
{ $mul: { "stats.views": 2, "pricing.base": 1.5 } } - 数组内字段不支持直接点号翻倍(如
"items.0.price"),需配合$[]或$[i]和arrayFilters - MongoDB 5.0+ 中字段更新顺序按字典序,但对
$mul自身无影响;不过若与其他操作符混用(如$set同名字段),顺序可能引发意外覆盖
性能与安全提醒
看似简单的一次 $mul,在高并发或大数据量场景下容易踩坑:
- 没有索引的查询条件(如
{ status: "active" })会导致全表扫描,updateMany()可能长时间阻塞 - 翻倍操作不可逆,生产环境务必先在副本集从节点或备份库上验证效果
- Decimal128 字段翻倍后位数增加(如
Decimal128("99.99") × 2 = Decimal128("199.98")),注意下游系统是否支持扩展精度 - 空操作(
{ $mul: {} })在 MongoDB 5.0+ 中合法且静默跳过,但旧版本会报错,升级后需检查脚本兼容性











