MongoDB中Double类型字段随机被存为Int64的问题求助
问题分析与解决方案
可能的原因
ReactiveMongo 0.19.0的默认BSON序列化逻辑存在特殊行为:当Scala Double 值为整数形式(如 100.0)时,会自动将其序列化为MongoDB的Int64类型,而非严格保留Double类型。这种自动类型转换是出于存储空间优化的设计,但会导致字段类型随机不一致——带小数的数值被存为Double,整数形式的Double则被转成Int64,哪怕你已经显式定义字段类型为Option[Double]。
解决方案
1. 自定义BSON序列化器强制保留Double类型
为MyModel的amount字段编写自定义BSON读写器,确保无论数值是否为整数,都被序列化为BSON Double类型。示例代码如下:
import reactivemongo.api.bson._ // 自定义Double类型的BSON处理逻辑,强制输出为BSONDouble implicit val doubleHandler: BSONHandler[BSONDouble, Double] = new BSONHandler[BSONDouble, Double] { override def read(bson: BSONDouble): Double = bson.value override def write(t: Double): BSONDouble = BSONDouble(t) } // 为MyModel生成带自定义处理的BSON格式 implicit val myModelFormat: BSONDocumentHandler[MyModel] = Macros.handler[MyModel]
通过该方式,所有Double类型的值都会被强制序列化为BSONDouble,对应MongoDB中的Double类型,不会再被自动转换为Int64。
2. 升级ReactiveMongo版本
ReactiveMongo 0.20.x及以上的稳定版本修复了这个默认序列化的行为问题,会严格按照Scala的类型映射BSON类型。如果项目依赖允许,升级到较新版本可直接解决问题,注意同步核对Play Framework与ReactiveMongo的版本兼容性。
3. 临时快速验证方案(不推荐作为长期解决办法)
在插入前对amount字段做显式转换,强制保留Double类型特性:
val fixedDoc = doc.copy(amount = doc.amount.map(_ + 0.0))
但这只是临时 workaround,无法从根源解决问题,更推荐前两种方案。
内容的提问来源于stack exchange,提问作者John Deer
相关产品推荐
相关产品推荐

