Overview
在本指南中,您可以学习;了解MongoDB Rust驱动程序和 bson crate 如何表示BSON数据、如何在BSON和Rust类型之间进行转换以及直接在应用程序代码中使用BSON文档。
该驾驶员使用bson 包对BSON数据进行编码和解码,并使用 Serde框架对Rust类型进行序列化和反序列化。要学习;了解有关序列化的详情,请参阅 数据建模和序列化指南。
有关BSON 的详细信息以及BSON 类型的完整列表,请参阅MongoDB Server手册中的 BSON类型。
示例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 包使用 bson::Bson枚举对BSON值进行建模,并使用 bson::Document 结构体对BSON文档进行建模。
提示
如果您已经在使用 mongodb crate,则无需将 bson 添加为直接依赖项。该驾驶员会重新导出 bson,因此您可以从应用程序中将其导入,而无需在 Cargo.toml文件中添加单独的条目。
在Rust中表示BSON
bson crate 提供以下用于处理BSON数据的核心类型和宏:
bson::Bson:表示任何BSON值的枚举,例如字符串、整数、文档或大量。bson::Document:从 UTF-8 字符串键到表示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 包与 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反序列化回您的类型。
自定义序列化行为
bson 包提供表示BSON值类型的Rust类型,例如 ObjectId 和 DateTime,它们实现了Serialize 和 Deserialize。您可以将这些类型直接嵌入到域结构中,以控制如何将字段序列化为 BSON 和从BSON反序列化。
以下示例定义了一个 Order 结构体,该结构体使用 ObjectId 类型作为 _id字段,使用 DateTime 类型作为 delivery_date字段,确保这些字段作为相应的BSON 类型进行存储和检索:
struct Order { _id: ObjectId, item: String, delivery_date: DateTime, }
使用 UUID 值
包使用bson Uuid 类型对 UUID 值进行建模,该类型对应于子类型为0 x04 (UUID) 的BSON二进制值。使用适当的功能标志,您还可以通过uuid bson::uuid 模块与 箱集成。
您可以将 UUID 值直接嵌入到域类型中,如以下示例所示:
struct Session { id: Uuid, user_id: Uuid, created_at: DateTime, }
由于驾驶员和 bson 与 Serde 集成,因此 UUID 值会自动序列化为BSON二进制 UUID 并反序列化回相应的Rust类型。
使用原始BSON数据
对于性能敏感的工作负载,您可能希望检查或验证BSON文档,而不将它们完全反序列化为强类型Rust结构体。 bson 包为此目的公开了以下原始类型:
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传输格式表示形式,并将其写入磁盘。bson 包提供了 Document::to_vec() 方法,用于将文档编码为其BSON字节表示形式。
以下示例将示例餐厅文档写入文件:
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 包中的编码和解码助手旨在与MongoDB驱动程序和其他BSON库进行互操作,因此您可以在磁盘上和网络上使用相同的BSON表示形式。
其他资源
要进一步学习;了解本指南中描述的类型和方法,请参阅以下文档:
MongoDB Server手册中的BSON类型