使用doc!宏传u128属性时报`Bson: From<u128>`不满足如何解决
报错根因
MongoDB BSON 协议没有提供与 Rust u128 类型对应的原生标量类型:u32、i64 可以直接映射到 BSON 的 32 位整数、64 位整数类型,而 u128 超出了 BSON 原生整数的表示范围,序列化时无法匹配对应类型,因此触发报错。
解决方案
根据你的业务场景可选择以下任意一种方案:
方案1:序列化为 BSON Binary 类型(推荐)
该方案保留数值的二进制特性,同时支持精确匹配、范围查询,无精度损失:
use mongodb::bson::{Binary, doc}; use mongodb::bson::spec::BinarySubtype; pub async fn read_foo(client: mongodb::Client, key: u128) -> Option<mongodb::bson::Document> { // 统一使用大端序转换为字节数组,读写逻辑保持一致即可 let key_binary = Binary { subtype: BinarySubtype::Generic, bytes: key.to_be_bytes().to_vec() }; client .database("db") .collection("col") .find_one(doc! {"key": key_binary}, None) .await .expect("Could not connect to database") }
注意:写入数据时也需要用相同的端序逻辑将
u128转换为 Binary 类型再入库,保证读写匹配。
方案2:转为字符串存储(适合仅需精确匹配的场景)
如果不需要对 key 做数值范围查询,该方案实现成本最低:
pub async fn read_foo(client: mongodb::Client, key: u128) -> Option<mongodb::bson::Document> { client .database("db") .collection("col") .find_one(doc! {"key": key.to_string()}, None) .await .expect("Could not connect to database") }
方案3:serde 自定义序列化规则
如果你使用 serde 做 BSON 序列化/反序列化,可以给结构体字段添加自定义序列化逻辑,避免每次手动转换:
use serde::{Serialize, Deserialize}; use mongodb::bson::Binary; use mongodb::bson::spec::BinarySubtype; // 你的业务数据结构体 #[derive(Serialize, Deserialize)] struct BusinessDoc { #[serde(with = "u128_bson")] key: u128, // 其他字段省略 } mod u128_bson { use super::*; use serde::{Serializer, Deserializer, Deserialize}; pub fn serialize<S>(val: &u128, serializer: S) -> Result<S::Ok, S::Error> where S: Serializer, { Binary { subtype: BinarySubtype::Generic, bytes: val.to_be_bytes().to_vec(), }.serialize(serializer) } pub fn deserialize<'de, D>(deserializer: D) -> Result<u128, D::Error> where D: Deserializer<'de>, { let bin = Binary::deserialize(deserializer)?; let bytes: [u8; 16] = bin.bytes.try_into().map_err(serde::de::Error::custom)?; Ok(u128::from_be_bytes(bytes)) } }
内容的提问来源于stack exchange,提问作者0xba1
相关产品推荐
相关产品推荐

