数据建模与序列化
概述
在这份指南中,您可以了解Rust驱动程序如何处理BSON和Rust类型之间的转换。将Rust类型转换为BSON的过程称为序列化,而反向过程称为反序列化。
Rust语言使用静态类型系统,但BSON具有动态模式。为了处理Rust类型和BSON之间的转换,驱动程序和bson
库集成了Serde框架的功能。有关如何安装serde
crate的信息,请参阅serde在crates.io
crate注册表。
通过将serde
crate的功能实现到您的应用程序中,您可以使用自定义Rust类型,如结构和枚举来建模您的数据。
本指南包括以下部分
泛型类型参数
当您创建一个 Collection
实例时,您必须指定一个泛型类型参数来表示您的集合中文档的数据类型。有关指定泛型类型参数的更多信息,请参阅集合参数化部分的数据库和集合指南。
我们建议您定义并使用一个自定义类型来表示您的集合数据,而不是使用 Document
类型。
自定义数据模型
您可以使用任何实现了 Serialize
和 Deserialize
特性的 serde
包中的 Rust 数据类型作为 Collection
实例的泛型类型参数。要实现 Serialize
和 Deserialize
特性,您必须在定义 Rust 类型之前包含以下 derive
属性
自定义结构示例
以下代码定义了一个示例 Vegetable
结构,该结构实现了 serde
序列化特性
struct Vegetable { name: String, category: String, tropical: bool, }
以下代码使用 Vegetable
作为其泛型类型参数访问 vegetables
集合
let my_coll: Collection<Vegetable> = client .database("db") .collection("vegetables");
因为Collection
实例使用Vegetable
结构体进行了参数化,所以可以使用该类型执行CRUD操作。以下代码将一个Vegetable
实例插入到集合中
let calabash = Vegetable { name: "calabash".to_string(), category: "gourd".to_string(), tropical: true, }; my_coll.insert_one(calabash).await?;
多个参数化
如果你的集合包含多个模式,你可以为每个数据类型定义一个自定义类型,并为每种类型创建原始Collection
实例的副本。你可以使用clone_with_type()
方法创建Collection
实例的副本。
假设你最初使用一个名为Square
的结构体参数化了一个集合,但后来你意识到你想要将不同类型的数据(由Circle
结构体建模)插入到集合中。以下代码使用Square
类型参数化了一个集合,然后创建了一个使用Circle
类型参数化的集合副本
let shapes_coll: Collection<Square> = client .database("db") .collection("shapes"); // ... perform some operations with Square let shapes_coll: Collection<Circle> = shapes_coll.clone_with_type(); // ... perform some operations with Circle
自定义序列化
您可以使用serde
crate中的serialize_with
和deserialize_with
属性来修改Rust驱动程序的默认序列化和反序列化行为。属性是附加到结构体字段或枚举变体的可选元数据。
serde
crate提供了serialize_with
和deserialize_with
属性,它们接受辅助函数作为值。这些辅助函数自定义特定字段和变体的序列化和反序列化。要在字段上指定属性,在字段定义之前包含该属性
struct MyStruct { field1: String, // ... other fields }
在下文中,您可以找到使用 bson
库中的辅助函数实现常见序列化任务的示例。要查看这些辅助函数的完整列表,请参阅 serde_helpers API 文档。
将字符串序列化为 ObjectId
您可能希望在结构体中将文档的 _id
字段表示为十六进制字符串。要将十六进制字符串转换为 ObjectId
BSON 类型,请使用 serialize_hex_string_as_object_id
辅助函数作为 serialize_with
属性的值。以下示例将 serialize_with
属性附加到 _id
字段,以便驱动程序将十六进制字符串序列化为 ObjectId
类型
struct Order { _id: String, item: String, }
要了解驱动程序如何将示例 Order
结构体序列化为 BSON,请从以下选项中选择结构体 和 BSON 选项卡
let order = Order { _id: "6348acd2e1a47ca32e79f46f".to_string(), item: "lima beans".to_string(), };
{ "_id": { "$oid": "6348acd2e1a47ca32e79f46f" }, "item": "lima beans" }
将 DateTime 序列为字符串
您可能想在文档中将 DateTime
字段值表示为 ISO 格式的字符串,在 BSON 中。为了指定这种转换,请使用 serialize_bson_datetime_as_rfc3339_string
辅助函数作为附加到具有 DateTime
值的字段的 serialize_with
属性的值。以下示例将 serialize_with
属性附加到 delivery_date
字段,以便驱动程序将 DateTime
值序列化为字符串。
struct Order { item: String, delivery_date: DateTime, }
要查看驱动程序如何将示例 Order
结构序列化为 BSON,请从以下 结构 和 BSON 选项卡中选择
let order = Order { item: "lima beans".to_string(), delivery_date: DateTime::now(), };
{ "_id": { ... }, "item": "lima beans", "delivery_date": "2023-09-26T17:30:18.181Z" }
将 u32 序列为 f64
您可能想在文档中将 u32
字段值表示为 BSON 中的 f64
或 Double
类型。为了指定这种转换,请使用 serialize_u32_as_f64
辅助函数作为附加到具有 u32
值的字段的 serialize_with
属性的值。以下示例将 serialize_with
属性附加到 quantity
字段,以便驱动程序将 u32
值序列化为 Double
类型。
struct Order { item: String, quantity: u32, }
注意
u32 值的 BSON Double
表示形式与原始值相同。
其他属性和模块
除了辅助函数之外,bson
库还提供了处理序列化和反序列化的模块。要为特定字段或变体选择要使用的模块,请将 with
属性的值设置为模块名称
struct MyStruct { field1: u32, // ... other fields }
有关这些模块的完整列表,请参阅 serde_helpers API 文档。
serde
包提供了许多其他属性来自定义序列化。以下列表描述了一些常见的属性及其功能
rename
:使用指定的名称而不是 Rust 结构体或变体名称进行序列化和反序列化字段skip
:不序列化或反序列化指定的字段default
:如果在反序列化过程中不存在值,则使用Default::default()
的默认值
关于serde
属性的完整列表,请参阅serde 属性 API 文档。
更多信息
要了解更多关于 BSON 类型的信息,请参阅服务器手册中的BSON 类型。
有关演示 serde
功能的更多示例,请参阅开发者中心文章使用 Serde 在 Rust 中结构化数据。
要了解更多关于 Serde 框架的信息,请参阅Serde 文档。
API 文档
要了解更多关于本指南中提到的方法和类型,请参阅以下 API 文档
serialize_with Serde 属性
deserialize_with Serde 属性
with Serde 属性