Overview
En esta guía, puedes aprender a utilizar el controlador de Rust para realizar operaciones masivas.
Las operaciones masivas realizan múltiples operaciones de escritura en uno o más espacios de nombres. Un namespace es una combinación del nombre de la base de datos y el nombre de la colección, en el formato <database>.<collection>Dado que realiza operaciones masivas en una instancia Client, puede realizar operaciones masivas en cualquier espacio de nombres del clúster al que acceda su cliente.
Puedes realizar operaciones masivas para reducir el número de llamadas al servidor. En lugar de enviar una solicitud para cada operación, las operaciones masivas ejecutan varias operaciones dentro de una sola acción.
Esta guía incluye las siguientes secciones:
Datos de muestra presenta los datos de muestra que se utilizan en los ejemplos de operaciones masivas
Tipos de operaciones en bloque describe cómo utilizar los tipos
WriteModelpara realizar operaciones en bloque de inserción, reemplazo, actualizado y borradoTipo de retorno describe el valor de retorno del método
bulk_write()y cómo acceder a la información sobre la operación masiva.Modificar comportamiento describe cómo modificar el comportamiento predeterminado del
bulk_write()métodoEscribir en espacios de nombres mixtos describe cómo realizar una operación masiva en múltiples espacios de nombres en una llamada de método
Información adicional proporciona enlaces a recursos y documentación de la API para los tipos y métodos mencionados en esta guía
Importante
Para realizar operaciones de escritura masiva, asegúrese de que su aplicación cumpla con los siguientes requisitos:
Está conectado a MongoDB Server versión 8.0 o posterior.
Estás utilizando la versión del controlador Rust 3.0 o posterior.
Datos de muestra
Los ejemplos de esta guía utilizan los siguientes documentos de muestra, que se almacenan en la colección mushrooms de la base de datos db:
let docs = vec![ doc! {"name" : "portobello", "color" : "brown", "edible" : true }, doc! {"name" : "chanterelle", "color" : "yellow", "edible" : true }, doc! {"name" : "oyster", "color" : "white", "edible" : true }, doc! {"name" : "fly agaric", "color" : "red", "edible" : false }, ];
También puedes usar tipos de estructuras personalizadas para representar tus datos de muestras. Para un ejemplo que realiza una operación por lotes usando Mushroom structs para modelar los mismos datos, consulta el Ejemplo de inserción de structs en esta página.
Tipos de operaciones masivas
Para realizar una operación de escritura masiva, pasa un arreglo de instancias del enum WriteModel al método bulk_write().
En esta sección, puedes aprender cómo realizar las siguientes operaciones de guardado masivo definiendo sus respectivos tipos WriteModel:
Tip
También puede realizar varios tipos de operaciones de guardar en una única llamada al método bulk_write(). Para ver un ejemplo que pase un UpdateOneModel y un InsertOneModel a la misma llamada bulk_write(), consulte el Ejemplo de modificación de conducta en esta guía.
Insert
Para realizar una operación de inserción masiva, crea una instancia de InsertOneModel para cada documento que desees insertar. Luego, pase una lista de modelos al método bulk_write().
La siguiente tabla describe InsertOneModel campos que puedes configurar llamando a sus métodos de construcción correspondientes:
Campo | Descripción |
|---|---|
| The namespace on which the insert is performed. Type: Namespace |
| The document to insert. Type: Document |
Ejemplo de inserción de documentos
Este ejemplo realiza las siguientes acciones:
Especifica dos instancias
InsertOneModelen una matriz. CadaInsertOneModelrepresenta un documento que se insertará en el espacio de nombresdb.mushrooms.Pasa el arreglo de modelos al método
bulk_write().Imprime el número de documentos insertados.
let mushrooms: Collection<Document> = client.database("db").collection("mushrooms"); let models = vec![ InsertOneModel::builder() .namespace(mushrooms.namespace()) .document(doc! { "name": "lion's mane", "color": "white", "edible": true }) .build(), InsertOneModel::builder() .namespace(mushrooms.namespace()) .document(doc! { "name": "angel wing", "color": "white", "edible": false }) .build(), ]; let result = client.bulk_write(models).await?; println!("Inserted documents: {}", result.inserted_count);
Inserted documents: 2
Ejemplo de Insertar Estructuras
También puedes modelar tus documentos utilizando struct y realizar una inserción masiva de instancias de struct en el namespace db.mushrooms.
Este ejemplo realiza la misma operación que Ejemplo de inserción de documentos precedente, pero inserta instancias del siguiente tipo de estructura Mushroom:
struct Mushroom { name: String, color: String, edible: bool, }
El siguiente código utiliza el método insert_one_model() para construir un InsertOneModel a partir de cada instancia de Mushroom, luego inserta ambos modelos en una operación masiva:
let mushrooms: Collection<Mushroom> = client.database("db").collection("mushrooms"); let lions_mane = Mushroom { name: "lion's mane".to_string(), color: "white".to_string(), edible: true, }; let angel_wing = Mushroom { name: "angel wing".to_string(), color: "white".to_string(), edible: false, }; let lions_mane_model = mushrooms.insert_one_model(lions_mane)?; let angel_wing_model = mushrooms.insert_one_model(angel_wing)?; let result = client.bulk_write([lions_mane_model, angel_wing_model]).await?; println!("Inserted documents: {}", result.inserted_count);
Inserted documents: 2
Tip
Para obtener más información sobre los tipos de estructuras personalizadas y la serialización en el controlador Rust, consulte la guía en Modelado y serialización de datos.
Reemplaza
Para realizar una operación de reemplazo masivo, cree una instancia de ReplaceOneModel para cada documento que desee reemplazar. Luego, pase una lista de modelos al método bulk_write().
La siguiente tabla describe ReplaceOneModel campos que puedes configurar llamando a sus métodos de construcción correspondientes:
Campo | Descripción |
|---|---|
| The namespace on which the operation is performed. Type: Namespace |
| The filter that matches the document you want to replace. Type: Document |
| The replacement document. Type: Document |
| (Optional) The collation to use when sorting results. To learn more about collations,
see the Collations guide. Type: Document |
| (Optional) The index to use for the operation. To learn more about
indexes, see the Indexes guide. Type: Bson |
| (Optional) Whether a new document is created if no document matches the filter. By default, this field is set to false.Type: bool |
Ejemplo
Este ejemplo realiza las siguientes acciones:
Especifica dos instancias
ReplaceOneModelen un arreglo. Las instancias deReplaceOneModelcontienen instrucciones para reemplazar documentos que representan hongos en el espacio de nombresdb.mushrooms.Pasa el arreglo de modelos al método
bulk_write().Imprime el número de documentos modificados.
let mushrooms: Collection<Document> = client.database("db").collection("mushrooms"); let models = vec![ ReplaceOneModel::builder() .namespace(mushrooms.namespace()) .filter(doc! { "name": "portobello" }) .replacement(doc! { "name": "cremini", "color": "brown", "edible": true }) .build(), ReplaceOneModel::builder() .namespace(mushrooms.namespace()) .filter(doc! { "name": "oyster" }) .replacement(doc! { "name": "golden oyster", "color": "yellow", "edible": true }) .upsert(true) .build(), ]; let result = client.bulk_write(models).await?; println!("Modified documents: {}", result.modified_count);
Modified documents: 2
Update
Para realizar una actualización masiva, cree una instancia UpdateOneModel o UpdateManyModel para cada actualización que desee realizar. Luego, pase una lista de modelos al método bulk_write(). Un UpdateOneModel actualiza solo un documento que coincide con un filtro, mientras que un UpdateManyModel actualiza todos los documentos que coinciden con un filtro.
La siguiente tabla describe los campos UpdateOneModel y UpdateManyModel que puede configurar llamando a sus métodos de generación correspondientes:
Campo | Descripción |
|---|---|
| The namespace on which the operation is performed. Type: Namespace |
| The filter that matches one or more documents you want to update. When specified in an UpdateOneModel,
only the first matching document will be updated. When specified in an UpdateManyModel, all
matching documents will be updated.Type: Document |
| The update to perform. Type: UpdateModifications |
| (Optional) A set of filters specifying which array elements an update applies to if you are updating an
array-valued field. Type: Array |
| (Optional) The collation to use when sorting results. To learn more about collations,
see the Collations guide. Type: Document |
| (Optional) The index to use for the operation. To learn more about
indexes, see the Indexes guide. Type: Bson |
| (Optional) Whether a new document is created if no document matches the filter.
By default, this field is set to false.Type: bool |
Ejemplo
Este ejemplo realiza las siguientes acciones:
Especifica una instancia
UpdateOneModely unaUpdateManyModelen un arreglo. Estos modelos contienen instrucciones para actualizar documentos que representan setas en el espacio de nombresdb.mushrooms.Pasa el arreglo de modelos al método
bulk_write().Imprime el número de documentos modificados.
let mushrooms: Collection<Document> = client.database("db").collection("mushrooms"); let models = vec![ WriteModel::UpdateOne( UpdateOneModel::builder() .namespace(mushrooms.namespace()) .filter(doc! { "name": "fly agaric" }) .update(doc! { "$set": { "name": "fly amanita" } }) .upsert(true) .build(), ), WriteModel::UpdateMany( UpdateManyModel::builder() .namespace(mushrooms.namespace()) .filter(doc! { "color": "yellow" }) .update(doc! { "$set": { "color": "yellow/orange" } }) .build(), ), ]; let result = client.bulk_write(models).await?; println!("Modified documents: {}", result.modified_count);
Modified documents: 2
Borrar
Para realizar una eliminación masiva, cree una instancia DeleteOneModel o DeleteManyModel para cada operación de eliminación. A continuación, pase una lista de modelos al método bulk_write(). Un DeleteOneModel elimina solo un documento que coincide con un filtro, mientras que un DeleteManyModel elimina todos los documentos que coinciden con un filtro.
La siguiente tabla describe los campos DeleteOneModel y DeleteManyModel que puede configurar llamando a sus métodos de generación correspondientes:
Campo | Descripción |
|---|---|
| The namespace on which the operation is performed. Type: Namespace |
| The filter that matches one or more documents you want to delete. When specified in a DeleteOneModel,
only the first matching document will be deleted. When specified in a DeleteManyModel, all
matching documents will be deleted.Type: Document |
| (Optional) The collation to use when sorting results. To learn more about collations,
see the Collations guide. Type: Document |
| (Optional) The index to use for the operation. To learn more about
indexes, see the Indexes guide. Type: Bson |
Ejemplo
Este ejemplo realiza las siguientes acciones:
Especifica una instancia
DeleteOneModely unaDeleteManyModelen una matriz. Estos modelos contienen instrucciones para eliminar documentos que representan hongos en el espacio de nombresdb.mushrooms.Pasa el arreglo de modelos al método
bulk_write().Imprime el número de documentos eliminados.
let mushrooms: Collection<Document> = client.database("db").collection("mushrooms"); let models = vec![ WriteModel::DeleteOne( DeleteOneModel::builder() .namespace(mushrooms.namespace()) .filter(doc! { "color": "red" }) .build(), ), WriteModel::DeleteMany( DeleteManyModel::builder() .namespace(mushrooms.namespace()) .filter(doc! { "edible": true }) .build(), ), ]; let result = client.bulk_write(models).await?; println!("Deleted documents: {}", result.deleted_count);
Deleted documents: 4
Tipo de retorno
El método bulk_write() devuelve una instancia de estructura SummaryBulkWriteResult desde la cual puede acceder a información sobre su operación masiva.
El tipo SummaryBulkWriteResult tiene los siguientes campos:
inserted_count:: el número de documentos insertadosmatched_count: el número de documentos coincididos.modified_countla cantidad de documentos actualizadosupserted_countNúmero de documentos actualizados/insertadosdeleted_count:el número de documentos eliminados
También puede utilizar el método verbose_results() para ver información detallada sobre cada operación. El método verbose_results() devuelve una instancia de la estructura VerboseBulkWriteResult, que tiene los siguientes campos:
delete_results: los resultados de cada operación de eliminación exitosainsert_results:los resultados de cada operación de inserción exitosaupdate_results:los resultados de cada operación de actualización exitosasummaryun resumen de los resultados de cada tipo de operación
El siguiente ejemplo encadena el método verbose_results() al método bulk_write() e imprime los resultados de las operaciones de actualización y eliminación:
let models = vec![ WriteModel::DeleteOne( DeleteOneModel::builder() .namespace(mushrooms.namespace()) .filter(doc! { "name": "oyster" }) .build(), ), WriteModel::UpdateOne( UpdateOneModel::builder() .namespace(mushrooms.namespace()) .filter(doc! { "name": "chanterelle" }) .update(doc! { "$set": { "season": ["July", "August", "September"] } }) .build(), ), ]; let result = client.bulk_write(models).verbose_results().await?; println!( "Update results: {:?}\nDelete results: {:?}\n", result.update_results, result.delete_results );
Update results: {1: UpdateResult { matched_count: 1, modified_count: 1, upserted_id: None }} Delete results: {0: DeleteResult { deleted_count: 1 }}
Modificar comportamiento
Puede modificar el comportamiento del método bulk_write() ajustando los valores de los campos BulkWriteOptions. Para establecer estos campos de struct, encadene los métodos correspondientes de los campos al método bulk_write().
La estructura BulkWriteOptions contiene los siguientes campos:
Campo | Descripción | Valor por defecto |
|---|---|---|
| Whether the operations run in the order in which they were specified. When set to true, one failed operation prevents subsequent operations from running.When set to false, the server continues to attempt write operations if one fails.Type: bool |
|
| Whether document-level validation is bypassed. Type: bool |
|
| An arbitrary comment to help trace the operation through the database profiler, currentOp,
and logs. Type: Bson |
|
| A map of parameter names and values to apply to all operations within the bulk write.
Values must be constant or closed expressions that do not reference document fields. Type: Document |
|
| The write concern to use for this bulk operation. Type: WriteConcern | Hereda la preocupación de escritura del espacio de nombres |
Ejemplo
Este ejemplo intenta realizar operaciones de actualización e inserción en la colección mushrooms. El siguiente código establece el campo ordered a false encadenando el método ordered() al método bulk_write():
let mushrooms: Collection<Document> = client.database("db").collection("mushrooms"); let models = vec![ WriteModel::UpdateOne(UpdateOneModel::builder() .namespace(mushrooms.namespace()) .filter(doc! { "name": "portobello" }) .update(doc! { "$set": { "_id": 123 } }) .upsert(true) .build()), WriteModel::InsertOne(InsertOneModel::builder() .namespace(mushrooms.namespace()) .document(doc! { "name": "reishi", "color": "red/brown", "edible": true }) .build()), ]; let result = client.bulk_write(models).ordered(false).await?; println!( "Inserted documents: {}\nDeleted documents: {}", result.inserted_count, result.deleted_count );
Error: Error { kind: BulkWrite(BulkWriteError { write_concern_errors: [], write_errors: {0: WriteError { code: 66, code_name: None, message: "Plan executor error during update :: caused by :: Performing an update on the path '_id' would modify the immutable field '_id'", details: None }}, partial_result: Some(Summary(SummaryBulkWriteResult { inserted_count: 1, matched_count: 0, modified_count: 0, upserted_count: 0, deleted_count: 0 })) }), labels: ... }
El campo _id es inmutable y no se puede cambiar en una operación de actualización. Dado que la UpdateOneModel incluye instrucciones para actualizar este campo, la operación masiva devuelve una BulkWriteError y realiza solo la operación de inserción. Si estableces el campo ordered en true, el driver no intentará ninguna operación posterior tras la operación de actualización fallida, y el driver no insertará ningún documento.
Guardar en espacios de nombres mixtos
Los ejemplos anteriores en esta página realizan operaciones masivas en el namespace db.mushrooms. Sin embargo, puedes realizar guardados masivos en varios namespace en una sola llamada de método.
El siguiente ejemplo inserta un documento en el namespace ingredients.sweet y uno en el namespace meals.dessert:
let sweet: Collection<Document> = client .database("ingredients") .collection("sweet"); let dessert: Collection<Document> = client .database("meals") .collection("dessert"); let models = vec![ InsertOneModel::builder() .namespace(sweet.namespace()) .document(doc! { "name": "brown sugar", "price": 3.99 }) .build(), InsertOneModel::builder() .namespace(dessert.namespace()) .document(doc! { "name": "banana bread", "cook_time": 75 }) .build(), ]; let result = client.bulk_write(models).await?; println!("Inserted documents: {}", result.inserted_count);
Inserted documents: 2
Información Adicional
Para obtener más información sobre las operaciones por lotes, consulta Operaciones de escritura por lotes en el manual del servidor.