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

MongoDB Rust驱动无法使用u128数据类型的问题求助

在MongoDB Rust驱动中使用u128数据类型的解决方案

问题描述

尝试在MongoDB Rust驱动中使用u128类型作为文档字段时,遇到BSON序列化错误:u128 is not supported。以下是报错的示例代码:

use mongodb::{bson::{doc},
              options::{ClientOptions, ServerApi, ServerApiVersion},
              Client};

use serde::{Deserialize, Serialize};

#[derive(Debug, Deserialize, Serialize)]
struct Book {
    id    : u128,
    title : String,
    author: String,
}

#[tokio::main]
async fn main() -> mongodb::error::Result<()> {

    // 创建客户端配置
    let uri = "mongodb://localhost:27017";
    let mut client_options = ClientOptions::parse(uri).await?;

    // 设置Server API
    let server_api = ServerApi::builder().version(ServerApiVersion::V1).build();
    client_options.server_api = Some(server_api);
    client_options.app_name   = Some("Books".to_string());

    // 创建客户端并连接服务器
    let client = Client::with_options(client_options)?;

    // 获取数据库句柄
    let db = client.database("books");

    // 获取强类型集合句柄
    let collection = db.collection::<Book>("books");

    let books = vec![
        Book {
            id:     u128::pow(2,64),
            title:  "The Grapes of Wrath".to_string(),
            author: "John Steinbeck".to_string(),
        },
        Book {
            id:     u128::pow(2,64)+1,
            title:  "To Kill a Mockingbird".to_string(),
            author: "Harper Lee".to_string(),
        },
    ];

    // 插入文档
    collection.insert_many(books, None).await?;

    Ok(())
}

运行时错误信息:

Compiling mongodb_dr v0.1.0 (/Users/username/repo/git/rustwerk/mongodb_dr)
    Finished dev [unoptimized + debuginfo] target(s) in 0.84s
     Running `target/debug/mongodb_dr`
Error: Error { kind: BsonSerialization(SerializationError { message: "u128 is not supported" }), labels: {}, wire_version: Some(17), source: None }

解决方法

BSON原生不支持u128类型,需要通过自定义Serde序列化/反序列化逻辑,将u128转换为BSON支持的类型(如String或Decimal128)。

方案1:将u128序列化为字符串

通过Serde的with属性自定义转换逻辑,把u128转成字符串存储,读取时再转换回u128,适合仅作为标识、无需数值运算的场景:

use mongodb::{bson::{doc},
              options::{ClientOptions, ServerApi, ServerApiVersion},
              Client};

use serde::{Deserialize, Serialize, Deserializer, Serializer};

// 自定义u128转字符串的序列化函数
fn serialize_u128<S>(value: &u128, serializer: S) -> Result<S::Ok, S::Error>
where
    S: Serializer,
{
    serializer.serialize_str(&value.to_string())
}

// 自定义字符串转u128的反序列化函数
fn deserialize_u128<'de, D>(deserializer: D) -> Result<u128, D::Error>
where
    D: Deserializer<'de>,
{
    let s = String::deserialize(deserializer)?;
    s.parse().map_err(serde::de::Error::custom)
}

#[derive(Debug, Deserialize, Serialize)]
struct Book {
    #[serde(serialize_with = "serialize_u128", deserialize_with = "deserialize_u128")]
    id    : u128,
    title : String,
    author: String,
}

#[tokio::main]
async fn main() -> mongodb::error::Result<()> {
    let uri = "mongodb://localhost:27017";
    let mut client_options = ClientOptions::parse(uri).await?;

    let server_api = ServerApi::builder().version(ServerApiVersion::V1).build();
    client_options.server_api = Some(server_api);
    client_options.app_name   = Some("Books".to_string());

    let client = Client::with_options(client_options)?;
    let db = client.database("books");
    let collection = db.collection::<Book>("books");

    let books = vec![
        Book {
            id:     u128::pow(2,64),
            title:  "The Grapes of Wrath".to_string(),
            author: "John Steinbeck".to_string(),
        },
        Book {
            id:     u128::pow(2,64)+1,
            title:  "To Kill a Mockingbird".to_string(),
            author: "Harper Lee".to_string(),
        },
    ];

    collection.insert_many(books, None).await?;

    Ok(())
}

方案2:将u128转换为Decimal128

MongoDB支持Decimal128类型,可以直接存储大整数,适合需要数值运算的场景:

use mongodb::{bson::{doc, Decimal128},
              options::{ClientOptions, ServerApi, ServerApiVersion},
              Client};

use serde::{Deserialize, Serialize, Deserializer, Serializer};
use std::str::FromStr;

// 自定义u128转Decimal128的序列化函数
fn serialize_u128_to_decimal<S>(value: &u128, serializer: S) -> Result<S::Ok, S::Error>
where
    S: Serializer,
{
    let decimal = Decimal128::from_str(&value.to_string())
        .map_err(serde::ser::Error::custom)?;
    serializer.serialize_newtype_struct("Decimal128", &decimal)
}

// 自定义Decimal128转u128的反序列化函数
fn deserialize_decimal_to_u128<'de, D>(deserializer: D) -> Result<u128, D::Error>
where
    D: Deserializer<'de>,
{
    let decimal = Decimal128::deserialize(deserializer)?;
    decimal.to_string().parse().map_err(serde::de::Error::custom)
}

#[derive(Debug, Deserialize, Serialize)]
struct Book {
    #[serde(serialize_with = "serialize_u128_to_decimal", deserialize_with = "deserialize_decimal_to_u128")]
    id    : u128,
    title : String,
    author: String,
}

#[tokio::main]
async fn main() -> mongodb::error::Result<()> {
    let uri = "mongodb://localhost:27017";
    let mut client_options = ClientOptions::parse(uri).await?;

    let server_api = ServerApi::builder().version(ServerApiVersion::V1).build();
    client_options.server_api = Some(server_api);
    client_options.app_name   = Some("Books".to_string());

    let client = Client::with_options(client_options)?;
    let db = client.database("books");
    let collection = db.collection::<Book>("books");

    let books = vec![
        Book {
            id:     u128::pow(2,64),
            title:  "The Grapes of Wrath".to_string(),
            author: "John Steinbeck".to_string(),
        },
        Book {
            id:     u128::pow(2,64)+1,
            title:  "To Kill a Mockingbird".to_string(),
            author: "Harper Lee".to_string(),
        },
    ];

    collection.insert_many(books, None).await?;

    Ok(())
}

注意事项

  • 使用字符串存储时,无法直接在MongoDB中对该字段进行数值运算。
  • 使用Decimal128存储时,需确保MongoDB版本为3.4及以上,该版本开始支持Decimal128类型。

内容的提问来源于stack exchange,提问作者mabalenk

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 16:24:54