Overview
在本指南中,您可以学习;了解MongoDB Rust驱动程序和 bson crate 如何表示BSON数据、如何在BSON和Rust类型之间进行转换以及直接在应用程序代码中使用BSON文档。
该驱动程序使用 bson crate对BSON数据进行编码和解码,并使用 Serde框架对Rust类型进行序列化和反序列化。要学习;了解有关序列化的详情,请参阅 数据建模和序列化指南。
有关BSON 的详细信息以及BSON types的完整列表,请参阅MongoDB Server手册中的 BSON types。
示例BSON文档
本指南中的示例使用以下示例文档,它表示一家名为“Mongo's Pizza”的餐厅,并带有嵌入式解决文档和坐标:
let mut restaurant: Document = doc! { "address": { "street": "Pizza St", "zipcode": "10003", }, "coord": [-73.982_419_f64, 41.579_505_f64], "cuisine": "Pizza", "name": "Mongo's Pizza", };
BSON数据类型
MongoDB以称为BSON (二进制JSON)的二进制表示形式存储文档。BSON支持所有JSON数据结构类型,并添加了其他类型,例如日期、不同大小的整数、ObjectId 值、二进制数据等。
在Rust生态系统中,bson crate使用 bson::Bson枚举对BSON值进行建模,并使用 bson::Document 文档对BSON文档进行建模。
提示
如果您已经在使用 mongodb crate,则无需将 bson 添加为直接依赖项。该驱动程序会重新导出 bson,因此您可以从应用程序中将其导入,而无需在 Cargo.toml文件中添加单独的条目。
在Rust中表示BSON
bson crate 提供以下用于处理BSON数据的核心类型和宏:
bson::Bson:表示任何BSON值的枚举,例如string、整数、文档或数组。bson::Document:从 UTF-8 string 键到表示BSON文档的Bson 值的有序映射。bson!宏:从字面量构造Bson值。doc!宏:从文字构造Document。
示例,您可以使用doc! 宏来构建本指南开头所示的示例restaurant 文档。
您可以使用辅助方法将 Document 中的字段作为非类型化 Bson 值或强类型Rust值访问权限,如以下示例所示:
let value = restaurant.get("cuisine"); // Option<&Bson> let name = restaurant.get_str("name")?; // &str let address = restaurant.get_document("address")?; // &Document let zipcode = address.get_str("zipcode")?; // &str
修改BSON文档
您可以使用标准的类似映射操作(例如插入、替换和删除)来修改 Document 的内容,如以下示例所示:
restaurant = Document = doc! { "address": { "street": "Pizza St", "zipcode": "10003", }, "coord": [-73.982_419_f64, 41.579_505_f64], "cuisine": "Pizza", "name": "Mongo's Pizza", }; // Adds a new field restaurant_id restaurant.insert("restaurant_id", Bson::Int32(12345)); // Removes the cuisine field restaurant.remove("cuisine"); // Updates the name field if let Some(name) = restaurant.get_mut("name") { *name = Bson::String("Mongo's Pizza Place".to_string()); }
使用Rust类型对BSON文档进行建模
您可以使用自定义Rust类型对集合数据进行建模,而不是直接使用 Document 值。驱动程序和 bson crate 与 Serde 集成,以将您的类型序列化为BSON并将BSON反序列化回您的类型。要将自定义类型用作 mongodb::Collection 的泛型参数,请在结构体上派生 serde::Serialize 和 serde::Deserialize 特征。
以下示例定义了一个包含 name、cuisine 和 last_updated 字段的 Restaurant 结构体,使用此结构体对集合进行参数化,然后构造并插入一个 Restaurant文档,其中当前时间戳为 last_updated 值:
struct Restaurant { name: String, cuisine: String, last_updated: DateTime, } async fn use_collection(client: &Client) -> mongodb::error::Result<()> { let coll: Collection<Restaurant> = client .database("sample_restaurants") .collection("restaurants"); let doc = Restaurant { name: "Mongo's Pizza".to_string(), cuisine: "Pizza".to_string(), last_updated: DateTime::now(), }; coll.insert_one(doc).await?; Ok(()) }
使用自定义类型对集合进行参数化时,驱动程序会在写入时自动将您的类型序列化为BSON ,并在读取时将BSON反序列化回您的类型。
自定义序列化行为
The bson crate provides Rust types that represent BSON value types, such as ObjectId and DateTime, which implement Serialize and Deserialize.您可以将这些类型直接嵌入到域结构中,以控制如何将字段序列化为 BSON 和从BSON反序列化。
以下示例定义了一个 Order 结构体,该结构体使用 ObjectId 类型作为 _id字段,使用 DateTime 类型作为 delivery_date字段,确保这些字段作为相应的BSON 类型进行存储和检索:
struct Order { _id: ObjectId, item: String, delivery_date: DateTime, }
有关其他自定义选项,例如重命名字段、跳过字段以及如何使用辅助函数,请参阅 数据建模和序列化指南。
使用 UUID 值
bson crate 使用 Uuid 类型对 UUID 值进行建模,该类型对应于子类型为 0x04 (UUID) 的BSON二进制值。使用适当的功能标志,您还可以通过 bson::uuid 模块与 uuid crate 集成。
您可以将 UUID 值直接嵌入到域类型中,如以下示例所示:
struct Session { id: Uuid, user_id: Uuid, created_at: DateTime, }
由于驱动程序和 bson 与 Serde 集成,因此 UUID 值会自动序列化为BSON二进制 UUID 并反序列化回相应的Rust类型。
使用原始BSON数据
对于性能敏感的工作负载,您可能希望检查或验证BSON文档,而不将它们完全反序列化为强类型Rust结构体。bson crate 为此目的公开了以下原始类型:
RawDocument - 借用BSON文档的切片,类似于
strRawDocumentBuf - 自有BSON文档,类似于
StringRawBsonRef — 借用对单个原始BSON值的引用
您可以从字节切片或 Vec<u8> 创建 RawDocumentBuf,然后按键查找字段,如以下示例所示:
fn inspect_raw(bytes: Vec<u8>) -> Result<(), mongodb::bson::error::Error> { let raw = RawDocumentBuf::from_bytes(bytes)?; if let Some(name) = raw.get_str("name").ok() { println!("Restaurant name: {name}"); } Ok(()) }
这些原始 API 允许您访问权限特定字段并验证文档结构,而无需将整个文档分配或反序列化为更高级别的Rust类型。
将 BSON 写入文件
您可以将 Document 或任何 Serde 可序列化的类型序列化为其BSON传输格式表示形式,并将其写入磁盘。The bson crate provides the Document::to_vec() method to encode a 文档 to its BSON byte representation.
以下示例将示例餐厅文档写入文件:
fn write_bson_to_file(path: &str) -> std::io::Result<()> { let restaurant: Document = doc! { "address": { "street": "Pizza St", "zipcode": "10003", }, "coord": [-73.982_419_f64, 41.579_505_f64], "cuisine": "Pizza", "name": "Mongo's Pizza", }; // Encodes the document as BSON bytes let bytes = restaurant.to_vec() .expect("failed to encode document to BSON"); fs::write(path, &bytes) }
从文件中读取 BSON
要从文件读取BSON数据,您可以加载原始字节,然后将其解码为 Document 或其他 Serde 可序列化的类型。bson crate 支持直接从内存缓冲区或读取器读取文档。
以下示例从磁盘读取BSON文档并将其打印为扩展JSON以进行调试:
fn read_bson_from_file(path: &str) -> Result<(), Box<dyn std::error::Error>> { let bytes = fs::read(path)?; let mut cursor = Cursor::new(bytes); // Decodes a single document from the reader let doc = Document::from_reader(&mut cursor)?; // Converts to relaxed Extended JSON for logging let bson_value = Bson::Document(doc); let json = bson_value.into_relaxed_extjson(); // serde_json::Value println!("{}", json); Ok(()) }
bson crate中的编码和解码辅助程序旨在与MongoDB驱动程序和其他BSON库进行互操作,因此您可以在磁盘上和网络上使用相同的BSON表示形式。
其他资源
要进一步学习;了解本指南中描述的类型和方法,请参阅以下文档:
数据建模和序列化指南
bson crate API documentation for
Bson,Document, raw types, UUIDs, and Extended JSON helpersMongoDB Server手册中的BSON types