Overview
En esta guía, puede aprender a utilizar operaciones masivas en el controlador Java.
Para realizar una sola operación de creación, reemplazo, actualización o eliminación, puede usar el método correspondiente. Por ejemplo, para insertar un documento y reemplazar otro, puede usar el insertOne() y replaceOne(). Al usar estos métodos, el cliente realiza una llamada a la base de datos por cada operación.
Al usar una operación de escritura masiva, puede realizar varias operaciones de escritura con menos llamadas a la base de datos. Puede realizar operaciones de escritura masiva en los siguientes niveles:
Colección: Puede usar el
MongoCollection.bulkWrite()método para realizar operaciones de escritura masiva en una sola colección. En este método, cada tipo de operación de escritura requiere al menos una llamadaMongoCollection.bulkWrite()a la base de datos. Por ejemplo, integra varias operaciones de actualización en una sola llamada, pero realiza dos llamadas independientes a la base de datos para una operación de inserción y otra de reemplazo.Cliente: Si su aplicación se conecta a MongoDB Server versión 8.0 o posterior, puede usar el
MongoClient.bulkWrite()método para realizar operaciones de escritura masiva en varias colecciones y bases de datos del mismo clúster. Este método realiza todas las operaciones de escritura en una sola llamada a la base de datos.
Colección Escritura masiva
Las operaciones de escritura en bloque contienen una o más operaciones de escritura. Para realizar una operación de guardar masiva a nivel de colección, pasa un List de WriteModel documentos al método MongoCollection.bulkWrite(). Un WriteModel es un modelo que representa una operación de escritura.
El método MongoCollection.bulkWrite() realiza cada tipo de operación de escritura en una llamada a la base de datos independiente. Por ejemplo, al pasar los objetos DeleteOneModel, DeleteManyModel y ReplaceOneModel al método, este realiza dos llamadas: una para las operaciones de eliminación y otra para la operación de reemplazo.
Nota
Cuando el cliente divide las operaciones en llamadas de base de datos independientes, podría reordenarlas para mayor eficiencia si la operación de escritura masiva no está ordenada. Para obtener más información sobre el orden de ejecución de las operaciones, consulte la sección "Orden de ejecución".
Las siguientes secciones muestran cómo crear y usar cada documento WriteModel. Los ejemplos de cada sección utilizan los siguientes documentos de la colección people:
{ "_id": 1, "name": "Karen Sandoval", "age": 31 } { "_id": 2, "name": "William Chin", "age": 54 } { "_id": 8, "name": "Shayla Ray", "age": 20 }
Para obtener más información sobre los métodos y clases mencionados en esta sección, consulte la siguiente documentación de API:
Operación de inserción
Para insertar un documento, cree un InsertOneModel que especifique el documento que desea insertar. Para insertar varios documentos, debe crear un InsertOneModel para cada uno.
Ejemplo
El siguiente ejemplo crea un InsertOneModel para dos documentos que describen personas:
InsertOneModel<Document> juneDoc = new InsertOneModel<>(new Document("name", "June Carrie") .append("age", 17)); InsertOneModel<Document> kevinDoc = new InsertOneModel<>(new Document("name", "Kevin Moss") .append("age", 22));
Importante
Al ejecutar un bulkWrite(), el InsertOneModel no puede insertar un documento con un _id ya existente en la colección. En su lugar, el método lanza un MongoBulkWriteException.
El siguiente ejemplo intenta insertar dos documentos donde _id es 1 y 3:
try { List<WriteModel<Document>> bulkOperations = new ArrayList<>(); // Creates instructions to insert documents InsertOneModel<Document> doc1 = new InsertOneModel<>(new Document("_id", 1)); InsertOneModel<Document> doc3 = new InsertOneModel<>(new Document("_id", 3)); bulkOperations.add(doc1); bulkOperations.add(doc3); // Runs a bulk write operation for the specified insert WriteModels collection.bulkWrite(bulkOperations); // Prints a message if any exceptions occur during the bulk write operation } catch (MongoBulkWriteException e){ System.out.println("A MongoBulkWriteException occurred with the following message: " + e.getMessage()); }
A continuación se muestra la salida del código anterior:
A MongoBulkWriteException occurred with the following message: Bulk write operation error on server sample-shard-00-02.pw0q4.mongodb.net:27017. Write errors: [BulkWriteError{index=0, code=11000, message='E11000 duplicate key error collection: crudOps.bulkWrite index: _id_ dup key: { _id: 1 }', details={}}].
Para ver por qué no se insertó el documento con el _id de,3 consulte la sección Orden de ejecución.
Para obtener más información sobre los métodos y clases mencionados en esta sección, consulte la documentación de la API InsertOneModel.
Operación de reemplazo
Para realizar una operación de reemplazo, cree un ReplaceOneModel que especifique un filtro de consulta para el documento que desea reemplazar con el documento de reemplazo.
Importante
Al realizar un bulkWrite(), el ReplaceOneModel no puede realizar cambios en un documento que violen los límites de índice único en la colección, y el modelo no reemplaza un documento si no hay coincidencias con tu filtro de query.
Ejemplo
El siguiente ejemplo crea un ReplaceOneModel para reemplazar un documento donde el _id es 1 con un documento que contiene un campo location agregado:
ReplaceOneModel<Document> celineDoc = new ReplaceOneModel<>( Filters.eq("_id", 1), new Document("name", "Celine Stork") .append("location", "San Diego, CA"));
Si varios documentos coinciden con el filtro de consulta especificado en la instancia ReplaceOneModel, la operación reemplaza el primer resultado. Puede especificar una ordenación en una instancia ReplaceOptions para aplicar un orden a los documentos coincidentes antes de que el servidor realice la operación de reemplazo, como se muestra en el siguiente código:
ReplaceOptions options = ReplaceOptions.sort(Sorts.ascending("_id"));
Para obtener más información sobre los métodos y clases mencionados en esta sección, consulte los siguientes recursos:
Documentación de la API deReplaceOneModel
Documentación dela API de ReplaceOptions
Explicación manualdel servidor de índices únicos
Operación de actualización
Para realizar una operación de actualización, cree un UpdateOneModel o un UpdateManyModel especificando un filtro de consulta para los documentos que desea actualizar con las actualizaciones.
UpdateOneModel actualiza el primer documento que coincide con su filtro de consulta y UpdateManyModel actualiza todos los documentos que coinciden con su filtro de consulta.
Importante
Al ejecutar un bulkWrite(), UpdateOneModel y UpdateManyModel no pueden realizar cambios en un documento que violen las restricciones de índice único en la colección, y los modelos no actualizan ningún documento si no hay coincidencias con su filtro de consulta.
Ejemplo
El siguiente ejemplo crea un UpdateOneModel para actualizar el campo age en un documento donde el _id es 2:
UpdateOneModel<Document> updateDoc = new UpdateOneModel<>( Filters.eq("_id", 2), Updates.set("age", 31));
Si varios documentos coinciden con el filtro de query especificado en la instancia UpdateOneModel, la operación actualiza el primer resultado. Puedes especificar un ordenamiento en una instancia UpdateOptions para aplicar un orden a los documentos coincidentes antes de que el servidor realice la operación de actualización, como se muestra en el siguiente código:
UpdateOptions options = UpdateOptions.sort(Sorts.ascending("_id"));
Para obtener más información sobre los métodos y clases mencionados en esta sección, consulte los siguientes recursos:
UpdateOneModel API documentation
Documentación de la APIUpdateManyModel
UpdateOptions API documentation
Explicación manual del servidorde índices únicos
Operación de eliminación
Para realizar una operación de eliminación, cree un DeleteOneModel o un DeleteManyModel especificando un filtro de consulta para los documentos que desea eliminar.
DeleteOneModel elimina el primer documento que coincide con su filtro de consulta y DeleteManyModel elimina todos los documentos que coinciden con su filtro de consulta.
Importante
Al ejecutar un bulkWrite(), DeleteOneModel y DeleteManyModel no eliminan ningún documento si no hay coincidencias con su filtro de consulta.
Ejemplo
El siguiente ejemplo crea un DeleteOneModel para eliminar un documento donde el _id es 1:
DeleteOneModel<Document> deleteDoc = new DeleteOneModel<>(Filters.eq("_id", 1));
Para obtener más información sobre los métodos y clases mencionados en esta sección, consulte la siguiente documentación de API:
Orden de ejecución
El método bulkWrite() acepta un BulkWriteOptions opcional como segundo parámetro para especificar si la ejecución de las operaciones masivas está ordenada o no.
Ejecución ordenada
De forma predeterminada, el método bulkWrite() ejecuta las operaciones masivas en orden. Esto significa que las operaciones masivas se ejecutan en el orden en que se añadieron a la lista hasta que se produzca un error, si lo hay.
Ejemplo
El siguiente ejemplo realiza estas operaciones masivas:
Una operación que inserta un documento con un valor
namede"Zaynab Omar"y un valoragede37Una operación que reemplaza el documento donde
_ides1con un nuevo documento que contiene el campolocationUna operación que actualiza el documento con un valor
namede"Zaynab Omar"y cambia elnamea"Zaynab Hassan"Una operación que elimina todos los documentos donde el valor
agees mayor que50
List<WriteModel<Document>> bulkOperations = new ArrayList<>(); // Creates instructions to insert a document InsertOneModel<Document> insertDoc = new InsertOneModel<>(new Document("_id", 6) .append("name", "Zaynab Omar") .append("age", 37)); // Creates instructions to replace the first document matched by the query ReplaceOneModel<Document> replaceDoc = new ReplaceOneModel<>(Filters.eq("_id", 1), new Document("name", "Sandy Kane") .append("location", "Helena, MT")); // Creates instructions to update the first document matched by the query UpdateOneModel<Document> updateDoc = new UpdateOneModel<>(Filters.eq("name", "Zaynab Omar"), Updates.set("name", "Zaynab Hassan")); // Creates instructions to delete all documents matched by the query DeleteManyModel<Document> deleteDoc = new DeleteManyModel<>(Filters.gt("age", 50)); bulkOperations.add(insertDoc); bulkOperations.add(replaceDoc); bulkOperations.add(updateDoc); bulkOperations.add(deleteDoc); // Runs a bulk write operation for the specified the insert, replace, update, and delete WriteModels in order collection.bulkWrite(bulkOperations);
Después de ejecutar este ejemplo, su colección contendrá el siguiente documento:
{ "_id": 1, "name": "Sandy Kane", "location": "Helena, MT" } { "_id": 8, "name": "Shayla Ray", "age": 20 } { "_id": 6, "name": "Zaynab Hassan", "age": 37 }
Ejecución desordenada
También puede ejecutar operaciones masivas en cualquier orden especificando "false" en el método order() de BulkWriteOptions. Esto significa que todas las operaciones de escritura se ejecutan independientemente de los errores y, si se producen, la operación masiva los reporta al final.
Agregando al ejemplo anterior, se incluye lo siguiente, se especifican las operaciones masivas a ejecutar en cualquier orden:
BulkWriteOptions options = new BulkWriteOptions().ordered(false); // Runs a bulk write operation for the specified insert, replace, update, and delete WriteModels in any order collection.bulkWrite(bulkOperations, options);
Nota
Las operaciones masivas desordenadas no garantizan el orden de ejecución. El orden puede variar según la forma en que se enumeran para optimizar el tiempo de ejecución.
En el ejemplo anterior, si el método bulkWrite() decidió realizar la operación de inserción después de la operación de actualización, no se produce ningún cambio con esta última, ya que el documento no existe en ese momento. Su colección contiene entonces los siguientes documentos:
{ "_id": 1, "name": "Sandy Kane", "location": "Helena, MT" } { "_id": 8, "name": "Shayla Ray", "age": 20 } { "_id": 6, "name": "Zaynab Omar", "age": 37 }
Para obtener más información sobre los métodos y clases mencionados en esta sección, consulte la siguiente documentación de API:
Ejemplo de escritura masiva: archivo completo
Nota
Configuración de ejemplo
Este ejemplo se conecta a una instancia de MongoDB mediante una URI de conexión. Para obtener más información sobre cómo conectarse a su instancia de MongoDB, consulte Guía para crear un MongoClient. Este ejemplo también utiliza la movies colección de la sample_mflix base de datos incluida en los conjuntos de datos de ejemplo de Atlas. Puede cargarlos en su base de datos en la versión gratuita de MongoDB Atlas siguiendo la guía de introducción de MongoDB.
El siguiente código es un archivo completo e independiente que realiza las siguientes acciones:
Crea una lista de instancias de las clases
InsertOneModel,UpdateOneModel,DeleteOneModelyReplaceOneModel.Ejecuta una operación
bulkWrite()ordenada que realiza las escrituras especificadas en la lista de modelos.
// Runs bulk write operations on a collection by using the Java driver package org.example; import java.util.Arrays; import org.bson.Document; import com.mongodb.MongoException; import com.mongodb.bulk.BulkWriteResult; import com.mongodb.client.MongoClient; import com.mongodb.client.MongoClients; import com.mongodb.client.MongoCollection; import com.mongodb.client.MongoDatabase; import com.mongodb.client.model.DeleteOneModel; import com.mongodb.client.model.InsertOneModel; import com.mongodb.client.model.ReplaceOneModel; import com.mongodb.client.model.UpdateOneModel; import com.mongodb.client.model.UpdateOptions; public class BulkWrite { public static void main(String[] args) { // Replace the uri string with your MongoDB deployment's connection string String uri = "<connection string uri>"; try (MongoClient mongoClient = MongoClients.create(uri)) { MongoDatabase database = mongoClient.getDatabase("sample_mflix"); MongoCollection<Document> collection = database.getCollection("movies"); // Runs a bulk write operation for the specified insert, update, delete, and replace operations BulkWriteResult result = collection.bulkWrite( Arrays.asList( new InsertOneModel<>(new Document("name", "A Sample Movie")), new InsertOneModel<>(new Document("name", "Another Sample Movie")), new InsertOneModel<>(new Document("name", "Yet Another Sample Movie")), new UpdateOneModel<>(new Document("name", "A Sample Movie"), new Document("$set", new Document("name", "An Old Sample Movie")), new UpdateOptions().upsert(true)), new DeleteOneModel<>(new Document("name", "Yet Another Sample Movie")), new ReplaceOneModel<>(new Document("name", "Yet Another Sample Movie"), new Document("name", "The Other Sample Movie").append("runtime", "42")) )); // Prints the number of inserted, updated, and deleted documents System.out.println("Result statistics:" + "\ninserted: " + result.getInsertedCount() + "\nupdated: " + result.getModifiedCount() + "\ndeleted: " + result.getDeletedCount()); } } }
Result statistics: inserted: 3 updated: 2 deleted: 1
Escritura masiva del cliente
Al conectarse a una implementación con MongoDB Server 8.0 o posterior, puede usar el método MongoClient.bulkWrite() para escribir en varias bases de datos y colecciones del mismo clúster. El método MongoClient.bulkWrite() realiza todas las operaciones de escritura en una sola llamada.
El método MongoClient.bulkWrite() toma una lista de instancias ClientNamespacedWriteModel para representar diferentes operaciones de escritura. Puedes construir instancias de la interfaz ClientNamespacedWriteModel utilizando métodos de instancia. Por ejemplo, una instancia de ClientNamespacedInsertOneModel representa una operación para insertar un documento, y puedes crear este modelo utilizando el método ClientNamespacedWriteModel.insertOne().
Nota
Errores de escritura masiva
Si alguna de las operaciones de escritura falla, el controlador genera un ClientBulkWriteException y no realiza ninguna otra operación individual. ClientBulkWriteException incluye un BulkWriteError al que se puede acceder mediante el método ClientBulkWriteException.getWriteErrors(), que proporciona detalles de la falla individual.
Los modelos y sus métodos de instancia correspondientes se describen en la siguiente tabla.
Modelo | Método de instancia | Descripción | Parámetros |
|---|---|---|---|
|
| Crea un modelo para insertar un documento en |
|
|
| Crea un modelo para actualizar el primer documento en |
Debe pasar un valor para el parámetro |
|
| Crea un modelo para actualizar todos los documentos en |
Debe pasar un valor para el parámetro |
|
| Crea un modelo para reemplazar el primer documento en |
|
|
| Crea un modelo para eliminar el primer documento en |
|
|
| Crea un modelo para eliminar todos los documentos en |
|
Las siguientes secciones proporcionan ejemplos de cómo utilizar el método de cliente bulkWrite().
Para obtener más información sobre los métodos y clases mencionados en esta sección, consulte la siguiente documentación de API:
Insertar ejemplo
Este ejemplo muestra cómo usar el método bulkWrite() para insertar dos documentos. Un documento se inserta en la colección db.people y el otro en la colección db.things. La instancia MongoNamespace define las bases de datos y colecciones a las que se aplica cada operación de escritura.
MongoNamespace peopleNamespace = new MongoNamespace("db", "people"); MongoNamespace thingsNamespace = new MongoNamespace("db", "things"); List<ClientNamespacedWriteModel> bulkOperations = new ArrayList<>(); bulkOperations.add(ClientNamespacedWriteModel .insertOne( peopleNamespace, new Document("name", "Julia Smith") ) ); bulkOperations.add(ClientNamespacedWriteModel .insertOne( thingsNamespace, new Document("object", "washing machine") ) ); ClientBulkWriteResult result = mongoClient.bulkWrite(bulkOperations);
Ejemplo de actualización
El siguiente ejemplo muestra cómo utilizar el método bulkWrite() para actualizar documentos existentes en las colecciones db.people y db.things:
MongoNamespace peopleNamespace = new MongoNamespace("db", "people"); MongoNamespace thingsNamespace = new MongoNamespace("db", "things"); List<ClientNamespacedWriteModel> bulkOperations = new ArrayList<>(); bulkOperations.add(ClientNamespacedWriteModel.updateOne( peopleNamespace, Filters.eq("name", "Freya Polk"), Updates.inc("age", 1) ) ); bulkOperations.add(ClientNamespacedWriteModel.updateMany( thingsNamespace, Filters.eq("category", "electronic"), Updates.set("manufacturer", "Premium Technologies") ) ); ClientBulkWriteResult result = mongoClient.bulkWrite(bulkOperations);
Este ejemplo incrementa el valor del campo age en 1 en el documento cuyo valor name es "Freya Polk" en la colección people. También establece el valor del campo manufacturer en "Premium Technologies" en todos los documentos cuyo valor category es "electronic" en la colección things.
Si varios documentos coinciden con el filtro de consulta especificado en una ClientNamespacedUpdateOneModel instancia, la operación actualiza el primer resultado. Puede especificar un orden de clasificación en una instancia ClientUpdateOneOptions para aplicarlo a los documentos coincidentes antes de que el controlador realice la operación de actualización, como se muestra en el siguiente código:
ClientUpdateOneOptions options = ClientUpdateOneOptions .clientUpdateOneOptions() .sort(Sorts.ascending("_id"));
Ejemplo de reemplazo
El siguiente ejemplo muestra cómo utilizar el método bulkWrite() para reemplazar documentos existentes en las colecciones db.people y db.things:
MongoNamespace peopleNamespace = new MongoNamespace("db", "people"); MongoNamespace thingsNamespace = new MongoNamespace("db", "things"); List<ClientNamespacedWriteModel> bulkOperations = new ArrayList<>(); bulkOperations.add(ClientNamespacedWriteModel.replaceOne( peopleNamespace, Filters.eq("_id", 1), new Document("name", "Frederic Hilbert") ) ); bulkOperations.add(ClientNamespacedWriteModel.replaceOne( thingsNamespace, Filters.eq("_id", 1), new Document("object", "potato") ) ); ClientBulkWriteResult result = mongoClient.bulkWrite(bulkOperations);
Tras la correcta ejecución de este ejemplo, el documento con un valor _id de 1 en la colección people se reemplaza por un nuevo documento. El documento de la colección things con un valor _id de 1 se reemplaza por un nuevo documento.
Si varios documentos coinciden con el filtro de consulta especificado en una instancia ClientNamespacedReplaceOneModel, la operación reemplaza el primer resultado. Puede especificar un orden de clasificación en una instancia ClientReplaceOneOptions para aplicar un orden a los documentos coincidentes antes de que el controlador realice la operación de reemplazo, como se muestra en el siguiente código:
ClientReplaceOneOptions options = ClientReplaceOneOptions .clientReplaceOneOptions() .sort(Sorts.ascending("_id"));
Opciones de escritura masiva
Puede pasar una instancia de ClientBulkWriteOptions al método bulkWrite() para especificar opciones al ejecutar las operaciones de escritura masiva.
Ejemplo de orden de ejecución
Por defecto, las operaciones individuales en una operación por lotes se ejecutan en el orden en que las especificas hasta que ocurre un error o se ejecutan correctamente. No obstante, puedes pasar false al método ordered() en la interfaz ClientBulkWriteOptions para realizar operaciones de guardar de manera desordenada. Al utilizar la opción no ordenada, una operación que produce errores no impide la ejecución de otras operaciones de escritura en la llamada al método bulkWrite().
El siguiente código establece el método ordered() en una instancia de ClientBulkWriteOptions y realiza una operación de escritura masiva para insertar múltiples documentos.
MongoNamespace namespace = new MongoNamespace("db", "people"); ClientBulkWriteOptions options = ClientBulkWriteOptions .clientBulkWriteOptions() .ordered(false); List<ClientNamespacedWriteModel> bulkOperations = new ArrayList<>(); bulkOperations.add( ClientNamespacedWriteModel.insertOne( namespace, new Document("_id", 1).append("name", "Rudra Suraj") ) ); // Causes a duplicate key error bulkOperations.add( ClientNamespacedWriteModel.insertOne( namespace, new Document("_id", 1).append("name", "Mario Bianchi") ) ); bulkOperations.add( ClientNamespacedWriteModel.insertOne( namespace, new Document("name", "Wendy Zhang") ) ); ClientBulkWriteResult result = mongoClient.bulkWrite(bulkOperations, options);
Aunque la operación de escritura que inserta un documento con una clave duplicada genera un error, las demás operaciones se ejecutan porque la operación de escritura no está ordenada.
Solución de problemas
Excepción de escritura masiva
Si el controlador detecta un error durante una operación de escritura masiva, lanza una MongoBulkWriteException. Un campo MongoBulkWriteException contiene un writeErrors campo que consiste en una lista de uno o más WriteError objetos asociados con la misma operación de escritura masiva.
Considere una colección con una regla de validación de esquema donde el valor del campo quantity debe ser de tipo int. En el siguiente ejemplo, el controlador genera una excepción MongoBulkWriteException al intentar insertar un documento con un valor de campo quantity de "three" y otro con un valor de campo quantity de "ten".
Exception in thread "main" com.mongodb.MongoBulkWriteException: Bulk write operation result had errors at com.mongodb.internal.connection.ProtocolHelper.getBulkWriteException(ProtocolHelper.java:258) ... at BulkWriteMultipleValidationErrorsExample.main(BulkWriteMultipleValidationErrorsExample.java:30) Caused by: com.mongodb.MongoWriteException: WriteError{code=121, message='Document failed validation', details={ operator: "$jsonSchema", schemaRules: { bsonType: "int", description: "must be an integer" }, offendingDocument: {"name":"Apple","quantity":"three"} }} at com.mongodb.internal.connection.WriteResultHelper.createWriteException(WriteResultHelper.java:50) at com.mongodb.internal.connection.ProtocolHelper.getBulkWriteException(ProtocolHelper.java:254) ... 19 more Caused by: com.mongodb.MongoWriteException: WriteError{code=121, message='Document failed validation', details={ operator: "$jsonSchema", schemaRules: { bsonType: "int", description: "must be an integer" }, offendingDocument: {"name":"Banana","quantity":"ten"} }} at com.mongodb.internal.connection.WriteResultHelper.createWriteException(WriteResultHelper.java:50) at com.mongodb.internal.connection.ProtocolHelper.getBulkWriteException(ProtocolHelper.java:254) ... 19 more
Para obtener más información sobre la validación del esquema, consulte Validación del esquema en la sección Entradas del manual del servidor.
Información Adicional
Documentación de la API
Para aprender más sobre los métodos y clases utilizados para realizar operaciones de escritura masiva en esta sección, consulta la siguiente documentación de API: