You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 22:08:33