MongoDB使用复杂多字段表达式实现原子更新报错如何解决?
问题原因
你当前使用的是MongoDB普通更新语法,该模式下$set字段仅支持写入固定常量值,无法识别聚合运算表达式、也无法引用文档自身的现有字段值,因此MongoDB会直接把你写的{ '$add': [ 'total', 0.25 ] }这类对象当成要写入total字段的值,触发数字类型转换失败的报错。
解决方案
方案1:使用MongoDB 4.2+ 聚合更新管道(支持单语句计算三个字段)
4.2及以上版本支持将更新操作的第二个参数替换为聚合管道数组,即可在更新中直接使用表达式计算、引用文档现有字段,操作本身为原子性:
// value为本次提交的投票分,替换为实际数值即可 db.Post.update( {"_id": id}, [ // 注意这里用数组包裹,代表聚合更新管道 { $set: { total: { $add: [ "$total", value ] }, size: { $add: [ "$size", 1 ] }, average: { $divide: [ { $add: [ { $multiply: [ "$size", "$average" ] }, value ] }, { $add: [ "$size", 1 ] } ] } } } ] )
注意引用文档现有字段时必须添加$前缀。
方案2:更精简的通用实现(兼容所有MongoDB版本)
你已经存储了total(总投票分)和size(总投票数)两个字段,完全不需要额外存储和计算average字段,average可以在查询时通过total / size实时计算得到。更新时直接用原生原子操作$inc即可,性能更高、兼容性更好:
db.Post.update( {"_id": id}, { $inc: { total: value, size: 1 } } )
内容的提问来源于stack exchange,提问作者IndigoFenix
相关产品推荐
相关产品推荐

