如何确保MongoDB中指定字段始终存储为Double类型?
问题:如何确保MongoDB字段始终存储为Double类型?
我通过单元测试验证插入MongoDB的字段类型,测试代码如下:
"insert big double to mongo" in { val doc: MyDocument = generateMyDocument() val newdoc = doc.copy(myDoubleField = 2394735300.0) dao.insertOne(newdoc, action).futureValue }
发现本该存储为Double类型的myDoubleField字段,赋值2394735300.0时被存为Int64,赋值24735300时被存为Int32,仅赋值2735300时才会被存为Double,这一现象令我困惑。我的insertOne方法代码如下:
def insertOne(doc: Doc, action: EventAction): Future[Doc] = { doc.createdAt = Some(InstantNow) doc.updatedAt = doc.createdAt (for { insertedDoc <- collection.insert.one(doc) .map({ case DefaultWriteResult(true, 1, _, _, _, _) => doc case dwr => throw new RuntimeException(s"$LogName was not inserted, something went wrong: $dwr") }) _ <- eventsCollection.insert.one(EventDocument(action, DataOperation.Create, dataType, None, doc._id, doc.metadata, None, None, None)) } yield insertedDoc) .recover({ case WriteResult.Code(DuplicateCode) => throw DuplicateKeyException(doc.uniqueIndexToString) }) }
请问如何确保该字段始终被存储为Double类型?
解决方案
1. 显式定义字段的MongoDB类型映射
在MyDocument的实体类中,通过注解强制指定myDoubleField的MongoDB存储类型为Double。以MongoDB Scala驱动的注解方式为例:
case class MyDocument( // 其他字段 @BsonProperty("myDoubleField") @BsonRepresentation(BsonType.DOUBLE) myDoubleField: Double )
这种方式会让驱动忽略数值的“整数特征”,始终将字段序列化为Double类型。
2. 确保赋值时的类型明确
即使数值是整数形式,也要保证赋值给myDoubleField的是明确的Double类型:
// 带.0后缀明确为Double val newdoc = doc.copy(myDoubleField = 2394735300.0) // 或通过显式转换确保类型 val intValue = 2394735300 val newdoc = doc.copy(myDoubleField = intValue.toDouble)
避免直接传入Int类型值,防止驱动自动将其序列化为整数类型。
3. 给集合添加Schema验证规则
在MongoDB中给目标集合设置Schema验证,强制myDoubleField必须为Double类型:
// 在MongoDB Shell中执行 db.runCommand({ collMod: "your_collection_name", validator: { $jsonSchema: { bsonType: "object", properties: { myDoubleField: { bsonType: "double" } } } } })
这样MongoDB会直接拒绝不符合类型要求的插入操作,从存储层面强制字段类型。
4. 自定义Codec控制序列化逻辑
如果默认驱动映射无法满足需求,可以自定义Codec来完全控制MyDocument的序列化过程:
class MyDocumentCodec extends Codec[MyDocument] { override def encode(writer: BsonWriter, value: MyDocument, encoderContext: EncoderContext): Unit = { writer.writeStartDocument() // 处理其他字段的序列化... writer.writeDouble("myDoubleField", value.myDoubleField) writer.writeEndDocument() } // 实现decode、getEncoderClass方法... }
将自定义Codec注册到MongoDB客户端后,会替代默认的序列化逻辑,确保字段类型符合预期。
内容的提问来源于stack exchange,提问作者John Deer
相关产品推荐
相关产品推荐

