Make the MongoDB docs better! We value your opinion. Share your feedback for a chance to win $100.
Click here >
Docs Menu
Docs Home
/ /

Trabajar con datos BSON

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.

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",
};

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.

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 valor Bson a partir de un literal.

  • doc! macro: Construye un Document a 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

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());
}

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:

#[derive(Serialize, Deserialize)]
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.

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:

#[derive(Serialize, Deserialize)]
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.

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:

#[derive(Serialize, Deserialize)]
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.

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 str

  • RawDocumentBuf - Documento BSON propio, similar a String

  • RawBsonRef - 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.

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)
}

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.

Para obtener más información sobre los tipos y métodos descritos en esta guía, consulta la siguiente documentación:

Volver

intercalación

En esta página