Overview
En esta guía, puedes aprender cómo el MongoDB Rust Driver y el bson caja represent BSON data, convertir entre BSON y tipos de Rust, y trabajar con documentos BSON directamente en el código de su aplicación.
El driver utiliza la caja bson para codificar y decodificar datos BSON y emplea el framework Serde para serializar y deserializar tus tipos Rust. Para saber más sobre la serialización, consulta la Guía sobre modelado y serialización de datos.
Para más información sobre BSON y la lista completa de BSON types, consulte BSON types en el manual del MongoDB Server.
Documento BSON de muestra
Los ejemplos en esta guía utilizan el siguiente documento de muestra, que representa un restaurante llamado "Mongo's Pizza" con un documento de dirección integrado y coordenadas:
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", };
Tipos de datos BSON
MongoDB almacena documentos en una representación binaria denominada BSON (JSON Binario). BSON admite todos los tipos de estructuras de datos JSON y agrega tipos adicionales, como fechas, enteros de diferentes tamaños, valores ObjectId, datos binarios y más.
En el ecosistema de Rust, la caja bson modela los valores BSON usando el enum bson::Bson y los documentos BSON usando la estructura bson::Document.
Tip
No necesitas agregar bson como una dependencia directa si ya estás usando la caja mongodb. El controlador reexporta bson, por lo que puede importarlo desde su aplicación sin una entrada separada en el archivo Cargo.toml.
Representar BSON en Rust
El bson caja proporciona los siguientes tipos centrales y macros para trabajar con datos BSON:
bson::Bson: Enum que representa cualquier valor BSON, como string, integer, documento o arreglo.bson::Document: Mapa ordenado de claves de string UTF-8 a valores Bson que representa un documento BSON.bson!macro: construye un valorBsona partir de un literal.doc!macro: Construye unDocumenta partir de un literal.
Por ejemplo, puedes usar la macro doc! para construir el documento de muestra restaurant que se muestra al inicio de esta guía.
Puedes acceder a los campos en un Document como valores no tipados Bson o como valores fuertemente tipados en Rust utilizando los métodos asistentes, como se muestra en el siguiente ejemplo:
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
Modificar un documento BSON
Puedes modificar el contenido de un Document utilizando operaciones estándar similares a un mapa, como inserción, reemplazo y eliminación, como se muestra en el siguiente ejemplo:
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()); }
Utiliza tipos Rust para modelar documentos BSON
En lugar de trabajar directamente con los valores de Document, puedes modelar los datos de tu colección con tipos personalizados de Rust. El driver y la bson caja se integran con Serde para serializar sus tipos a BSON y deserializar BSON de vuelta a sus tipos. Para utilizar un tipo personalizado como el parámetro genérico de un mongodb::Collection, deriva los traits serde::Serialize y serde::Deserialize en tu estructura.
El siguiente ejemplo define una estructura Restaurant que incluye los campos name, cuisine y last_updated, parametriza una colección utilizando esta estructura, y luego construye e inserta un documento Restaurant con la marca de tiempo actual como valor de 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(()) }
Cuando parametrizas una colección utilizando un tipo personalizado, el controlador serializa automáticamente tu tipo a BSON al escribir y deserializa BSON de vuelta a tu tipo al leer.
Personaliza el comportamiento de serialización
La caja bson proporciona tipos de Rust que representan tipos de valores BSON, como ObjectId y DateTime, que implementan Serialize y Deserialize. Puede incorporar estos tipos directamente en sus estructuras de dominio para controlar cómo se serializan y deserializan los campos en BSON y desde BSON.
El siguiente ejemplo define un struct Order que utiliza el tipo ObjectId para el campo _id y el tipo DateTime para el campo delivery_date, asegurando que estos campos se almacenen y recuperen como sus correspondientes BSON types:
struct Order { _id: ObjectId, item: String, delivery_date: DateTime, }
Para opciones de personalización adicionales, como renombrar campos, omitir campos y cómo usar funciones de asistente, consulte la guía de Modelado y Serialización de Datos.
Trabajar con valores UUID
La caja bson modela los valores UUID con la Uuid tipo, que corresponde a un valor binario BSON con subtipo 0x04 (UUID). Con los flags de funcionalidad adecuados, también puedes integrarte con la caja uuid a través del módulo bson::uuid.
Se pueden insertar valores UUID directamente en tus tipos de dominio, como se muestra en el siguiente ejemplo:
struct Session { id: Uuid, user_id: Uuid, created_at: DateTime, }
Debido a que el controlador y bson se integran con Serde, los valores UUID se serializan automáticamente como UUID binarios BSON y se deserializan nuevamente al tipo Rust apropiado.
Trabajar con datos BSON sin procesar
Para cargas de trabajo sensibles al rendimiento, podrías querer inspeccionar o validar documentos BSON sin deserializarlos completamente en estructuras Rust fuertemente tipadas. La caja bson expone los siguientes tipos primitivos para este propósito:
RawDocument - Porción prestada de un documento BSON, similar a
strRawDocumentBuf - Documento BSON propio, similar a
StringRawBsonRef - Referencia prestada a un único valor bruto de BSON
Puedes crear un RawDocumentBuf a partir de un byte slice o de un Vec<u8> y luego buscar campos por clave, como se muestra en el siguiente ejemplo:
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(()) }
Estas API sin procesar te permiten acceder a campos específicos y validar la estructura de documentos sin asignar ni deserializar documentos completos a tipos de alto nivel en Rust.
Guardar BSON en un archivo
Puedes serializar un Document o cualquier tipo serializable por Serde a su representación del formato de transmisión BSON y guardarlo en el disco. La caja bson proporciona el método Document::to_vec() para codificar un documento a su representación de bytes BSON.
El siguiente ejemplo escribe el documento de muestra del restaurante en un archivo:
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) }
Leer BSON desde un archivo
Para leer datos BSON de un archivo, puede cargar los bytes sin procesar y luego decodificarlos en un Document u otro tipo compatible con la serialización de Serde. La caja bson admite la lectura de documentos directamente desde un búfer de memoria o de un lector.
El siguiente ejemplo lee un documento BSON del disco y lo imprime como JSON extendido para la depuración:
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(()) }
Los asistentes de codificación y decodificación en el crate bson están diseñados para interoperar con los drivers de MongoDB y otras librerías BSON, de modo que se puede utilizar la misma representación BSON tanto en disco como a través de la red.
Recursos adicionales
Para obtener más información sobre los tipos y métodos descritos en esta guía, consulta la siguiente documentación:
bson caja API documentación para
Bson,Document, tipos en bruto, UUID y asistentes de Extended JSONBSON types en el manual de MongoDB Server