Docs Menu
Docs Home
/ /

Operaciones de escritura masiva

En esta guía, puede aprender cómo realizar múltiples operaciones de escritura en una sola llamada de base de datos mediante operaciones de escritura masiva.

Considera un escenario en el que quieres insertar un documento, actualizar varios otros documentos y luego borrar un documento. Si utiliza métodos individuales, cada operación requiere su propia llamada a la base de datos.

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: Puedes utilizar la 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 llamada a la base de datos. Por ejemplo, MongoCollection.bulkWrite() 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.

Los ejemplos de esta guía utilizan las colecciones y de los sample_restaurants.restaurants sample_mflix.movies conjuntos de datos de muestra de Atlas. Para aprender a crear un clúster gratuito de MongoDB Atlas y cargar los conjuntos de datos de muestra, consulte la guía "Comenzar con Atlas".

Los documentos de estas colecciones están modelados por las siguientes clases de datos de Kotlin:

data class Restaurant(
val name: String,
val borough: String,
val cuisine: String,
val stars: Int? = null,
)
data class Movie(
val title: String,
val year: Int,
val seen: Boolean? = null,
)

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.

Para cada operación de escritura que desee realizar, cree una instancia de una de las siguientes clases que heredan de WriteModel:

  • InsertOneModel

  • UpdateOneModel

  • UpdateManyModel

  • ReplaceOneModel

  • DeleteOneModel

  • DeleteManyModel

Las siguientes secciones muestran cómo crear y usar instancias de las clases anteriores. La sección "Realizar la operación masiva" muestra cómo pasar una lista de modelos al bulkWrite() método para realizar la operación masiva.

Para realizar una operación de inserción, cree una instancia InsertOneModel y especifique el documento que desea insertar.

El siguiente ejemplo crea una instancia de InsertOneModel:

val blueMoon = InsertOneModel(Restaurant("Blue Moon Grill", "Brooklyn", "American"))

Para insertar varios documentos, cree una instancia de InsertOneModel para cada documento.

Importante

Cuando se realiza una operación masiva, el InsertOneModel no puede indicar la inserción de un documento que tenga un valor de _id que ya exista en la colección. En esta situación, el controlador lanza un MongoBulkWriteException.

Para actualizar un documento, crea una instancia de UpdateOneModel y pasa los siguientes argumentos:

  • Un filtro de consulta que especifica los criterios utilizados para hacer coincidir los documentos de su colección

  • La operación de actualización que desea realizar. Para obtener más información sobre los operadores de actualización, consulte la guía "Operadores de actualización de campos" en el manual de MongoDB Server.

Una UpdateOneModel instancia especifica una actualización para el primer documento que coincide con su filtro de consulta.

El siguiente ejemplo crea una instancia de UpdateOneModel:

val updateOneFilter = Filters.eq(Restaurant::name.name, "White Horse Tavern")
val updateOneDoc = Updates.set(Restaurant::borough.name, "Queens")
val tavernUpdate = UpdateOneModel<Restaurant>(updateOneFilter, updateOneDoc)

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:

val opts = UpdateOptions().sort(Sorts.ascending(Restaurant::name.name))

Para actualizar varios documentos, cree una instancia de UpdateManyModel y pase los mismos argumentos que UpdateOneModel para. La UpdateManyModel clase especifica las actualizaciones para todos los documentos que coinciden con su filtro de consulta.

El siguiente ejemplo crea una instancia de UpdateManyModel para indicarle al controlador que actualice todos los documentos coincidentes:

val updateManyFilter = Filters.eq(Restaurant::name.name, "Wendy's")
val updateManyDoc = Updates.set(Restaurant::cuisine.name, "Fast food")
val wendysUpdate = UpdateManyModel<Restaurant>(updateManyFilter, updateManyDoc)

Una operación de reemplazo elimina todos los campos y valores de un documento específico y los reemplaza con los nuevos campos y valores que usted especifique. Para realizar una operación de reemplazo, cree una instancia de ReplaceOneModel y pase un filtro de consulta y los campos y valores con los que desea reemplazar el documento coincidente.

El siguiente ejemplo crea una instancia de ReplaceOneModel:

val replaceFilter = Filters.eq(Restaurant::name.name, "Cooper Town Diner")
val replaceDoc = Restaurant("Smith Town Diner", "Brooklyn", "American")
val replacement = ReplaceOneModel(replaceFilter, replaceDoc)

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:

val opts = ReplaceOptions().sort(Sorts.ascending(Restaurant::name.name))

Tip

Reemplazar varios documentos

Para reemplazar varios documentos, cree una instancia de ReplaceOneModel para cada documento.

Para borrar un documento, crea una instancia de DeleteOneModel y pasa un filtro de query que especifique el documento que deseas borrar. Una instancia DeleteOneModel proporciona instrucciones para eliminar solo el primer documento que coincida con tu filtro de query.

El siguiente ejemplo crea una instancia de DeleteOneModel:

val deleteOne = DeleteOneModel<Restaurant>(Filters.eq(
Restaurant::name.name,
"Morris Park Bake Shop"
))

Para eliminar varios documentos, cree una instancia de DeleteManyModel y utilice un filtro de consulta que especifique el documento que desea eliminar. Una instancia de DeleteManyModel proporciona instrucciones para eliminar todos los documentos que coincidan con su filtro de consulta.

El siguiente ejemplo crea una instancia de DeleteManyModel:

val deleteMany = DeleteManyModel<Restaurant>(Filters.eq(
Restaurant::cuisine.name,
"Experimental"
))

Después de definir una instancia de modelo para cada operación que desee realizar, pase una lista de estas instancias al método bulkWrite(). De forma predeterminada, el método ejecuta las operaciones en el orden especificado por la lista de modelos.

El siguiente ejemplo realiza múltiples operaciones de escritura utilizando el método bulkWrite():

val insertOneMdl = InsertOneModel(Restaurant("Red's Pizza", "Brooklyn", "Pizzeria"))
val updateOneMdl = UpdateOneModel<Restaurant>(
Filters.eq(Restaurant::name.name, "Moonlit Tavern"),
Updates.set(Restaurant::borough.name, "Queens")
)
val deleteManyMdl = DeleteManyModel<Restaurant>(
Filters.eq(Restaurant::name.name, "Crepe")
)
val bulkResult = collection.bulkWrite(
listOf(insertOneMdl, updateOneMdl, deleteManyMdl)
)
println(bulkResult)
AcknowledgedBulkWriteResult{insertedCount=1, matchedCount=5, removedCount=3,
modifiedCount=2, upserts=[], inserts=[BulkWriteInsert{index=0,
id=BsonObjectId{value=...}}]}

Si alguna de las operaciones de guardado falla, el driver de sincronización de Kotlin genera un BulkWriteError y no realiza ninguna operación adicional. BulkWriteError proporciona un campo details que incluye la operación que falló y detalles sobre la excepción.

Nota

Cuando el controlador ejecuta una operación masiva, utiliza la preocupación de escritura de la colección de destino. El controlador informa todos los errores de preocupación de escritura después de intentar todas las operaciones, independientemente del orden de ejecución.

El método bulkWrite() acepta opcionalmente un parámetro que especifica las opciones que puedes usar para configurar la operación de escritura masiva. Si no especifica ninguna opción, el driver realiza la operación masiva con la configuración por defecto.

La siguiente tabla describe los métodos de configuración que puede utilizar para configurar una instancia BulkWriteOptions:

Propiedad
Descripción

ordered()

If true, the driver performs the write operations in the order provided. If an error occurs, the remaining operations are not attempted.

If false, the driver performs the operations in an arbitrary order and attempts to perform all operations.
Defaults to true.

bypassDocumentValidation()

Specifies whether the update operation bypasses document validation. This lets you update documents that don't meet the schema validation requirements, if any exist. For more information about schema validation, see Schema Validation in the MongoDB Server manual.
Defaults to false.

comment()

Sets a comment to attach to the operation.

let()

Provides a map of parameter names and values to set top-level variables for the operation. Values must be constant or closed expressions that don't reference document fields.

El siguiente código crea opciones y usa la opción ordered(false) para especificar una escritura masiva desordenada. Luego, el ejemplo usa el método bulkWrite() para realizar una operación masiva:

val opts = BulkWriteOptions().ordered(false)
collection.bulkWrite(bulkOperations, opts)

Si alguna de las operaciones de escritura en una escritura masiva desordenada falla, el controlador de sincronización de Kotlin informa los errores solo después de intentar todas las operaciones.

Nota

Las operaciones masivas desordenadas no garantizan un orden de ejecución. El orden puede variar según la forma en que se enumeran para optimizar el tiempo de ejecución.

El método bulkWrite() devuelve un objeto BulkWriteResult. Puede acceder a la siguiente información desde una instancia BulkWriteResult:

Propiedad
Descripción

wasAcknowledged()

Indicates if the server acknowledged the write operation.

getDeletedCount()

The number of documents deleted, if any.

getInsertedCount()

The number of documents inserted, if any.

getInserts()

The list of inserted documents, if any.

getMatchedCount()

The number of documents matched for an update, if applicable.

getModifiedCount()

The number of documents modified, if any.

getUpserts()

The list of upserted documents, if any.

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().

Los modelos y sus métodos de instancia correspondientes se describen en la siguiente tabla.

Modelo
Método de instancia
Descripción
Parámetros

ClientNamespacedInsertOneModel

insertOne()

Crea un modelo para insertar un documento en namespace.

namespace:Base de datos y colección donde escribir

document:Documento para insertar

ClientNamespacedUpdateOneModel

updateOne()

Crea un modelo para actualizar el primer documento en namespace que coincide con filter.

namespace:Base de datos y colección donde escribir

filter:Filtro que selecciona qué documento actualizar

update:Actualización para aplicar al documento coincidente

updatePipeline:Actualizar canalización para aplicar al documento coincidente

options: (opcional) Opciones a aplicar al actualizar el documento

Debe pasar un valor para el parámetro update o updatePipeline.

ClientNamespacedUpdateManyModel

updateMany()

Crea un modelo para actualizar todos los documentos en namespace que coinciden con filter.

namespace:Base de datos y colección donde escribir

filter:Filtro que selecciona qué documentos actualizar

update:Actualización para aplicar a los documentos coincidentes

updatePipeline:Actualizar el flujo de trabajo para aplicarlo a los documentos coincidentes

options: (opcional) Opciones a aplicar al actualizar documentos

Debe pasar un valor para el parámetro update o updatePipeline.

ClientNamespacedReplaceOneModel

replaceOne()

Crea un modelo para reemplazar el primer documento en namespace que coincide con filter.

namespace:Base de datos y colección donde escribir

filter:Filtro que selecciona qué documento reemplazar

replacement:Documento de reemplazo

options: (opcional) Opciones a aplicar al reemplazar documentos

ClientNamespacedDeleteOneModel

deleteOne()

Crea un modelo para eliminar el primer documento en namespace que coincida con filter.

namespace:Base de datos y colección donde escribir

filter:Filtro que selecciona qué documento eliminar

option: (opcional) Opciones a aplicar al eliminar documento

ClientNamespacedDeleteManyModel

deleteMany()

Crea un modelo para eliminar todos los documentos en namespace que coincidan con filter.

namespace:Base de datos y colección donde escribir

filter:Filtro que selecciona qué documentos eliminar

option: (opcional) Opciones a aplicar al eliminar documentos

Las siguientes secciones proporcionan algunos ejemplos de cómo crear modelos y utilizar el método de cliente bulkWrite().

Este ejemplo muestra cómo crear modelos que contienen instrucciones para insertar dos documentos. Un documento se inserta en la colección sample_restaurants.restaurants y el otro documento se inserta en la colección sample_mflix.movies. La instancia MongoNamespace define la base de datos y la colección de destino a las que se aplica cada operación de guardar.

val restaurantToInsert = ClientNamespacedWriteModel
.insertOne(
MongoNamespace("sample_restaurants", "restaurants"),
Restaurant("Blue Moon Grill", "Brooklyn", "American")
)
val movieToInsert = ClientNamespacedWriteModel
.insertOne(
MongoNamespace("sample_mflix", "movies"),
Movie("Silly Days", 2022)
)

El siguiente ejemplo muestra cómo utilizar el método bulkWrite() para actualizar documentos existentes en las colecciones sample_restaurants.restaurants y sample_mflix.movies:

val restaurantUpdate = ClientNamespacedWriteModel
.updateOne(
MongoNamespace("sample_restaurants", "restaurants"),
Filters.eq(Restaurant::name.name, "Villa Berulia"),
Updates.inc(Restaurant::stars.name, 1)
)
val movieUpdate = ClientNamespacedWriteModel
.updateMany(
MongoNamespace("sample_mflix", "movies"),
Filters.eq(Movie::title.name, "Carrie"),
Updates.set(Movie::seen.name, true)
)

Este ejemplo incrementa el valor del campo stars en 1 en el documento cuyo valor name es "Villa Berulia" en la colección restaurants. También establece el valor del campo seen en true en todos los documentos cuyo valor title es "Carrie" en la colección movies.

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 servidor realice la operación de actualización, como se muestra en el siguiente código:

val options = ClientUpdateOneOptions
.clientUpdateOneOptions()
.sort(Sorts.ascending("_id"))

El siguiente ejemplo muestra cómo crear modelos para reemplazar documentos existentes en las colecciones sample_restaurants.restaurants y sample_mflix.movies:

val restaurantReplacement = ClientNamespacedWriteModel
.replaceOne(
MongoNamespace("sample_restaurants", "restaurants"),
Filters.eq("_id", 1),
Restaurant("Smith Town Diner", "Brooklyn", "American")
)
val movieReplacement = ClientNamespacedWriteModel
.replaceOne(
MongoNamespace("sample_mflix", "movies"),
Filters.eq("_id", 1),
Movie("Loving Sylvie", 1999)
)

Tras la correcta ejecución de este ejemplo, el documento con un valor _id de 1 en la colección restaurants se reemplaza por un nuevo documento. El documento de la colección movies con un valor _id de 1 también 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:

val options = ClientReplaceOneOptions
.clientReplaceOneOptions()
.sort(Sorts.ascending("_id"))

Después de definir una instancia ClientNamespacedWriteModel para cada operación que desee realizar, pase una lista de estas instancias al método bulkWrite() del cliente. De forma predeterminada, el método ejecuta las operaciones en el orden especificado.

El siguiente ejemplo realiza múltiples operaciones de escritura utilizando el método bulkWrite():

val restaurantNamespace = MongoNamespace("sample_restaurants", "restaurants")
val movieNamespace = MongoNamespace("sample_mflix", "movies")
val bulkOperations = listOf(
ClientNamespacedWriteModel
.insertOne(
restaurantNamespace,
Restaurant("Drea's", "Brooklyn", "Mexican")
),
ClientNamespacedWriteModel
.replaceOne(
movieNamespace,
Filters.eq("_id", 1),
Movie("Underneath It All", 2002)
)
)
val clientBulkResult = mongoClient
.bulkWrite(bulkOperations)
println(clientBulkResult.toString())
AcknowledgedSummaryClientBulkWriteResult{insertedCount=1, matchedCount=1, ...}

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.

Puede pasar una instancia de ClientBulkWriteOptions al método bulkWrite() para personalizar cómo el controlador realiza la operación de escritura masiva.

De forma predeterminada, el controlador ejecuta las operaciones individuales en una operación masiva en el orden que usted las especifica hasta que se produce un error o hasta que la operación se completa correctamente.

Sin embargo, puede pasar false al método ordered() al crear una instancia ClientBulkWriteOptions para indicar al controlador que realice operaciones de escritura desordenadas. Al usar la opción desordenada, una operación que genere errores no impide que el controlador ejecute otras operaciones de escritura en la operación de escritura masiva.

El siguiente código establece la opción ordered en false en una instancia de ClientBulkWriteOptions y realiza una operación de escritura masiva para insertar múltiples documentos.

val namespace = MongoNamespace("sample_restaurants", "restaurants")
val options = ClientBulkWriteOptions
.clientBulkWriteOptions()
.ordered(false)
val bulkOps = listOf(
ClientNamespacedWriteModel.insertOne(
namespace,
Document("_id", 1).append("name", "Freezyland")
),
// Causes a duplicate key error
ClientNamespacedWriteModel.insertOne(
namespace,
Document("_id", 1).append("name", "Coffee Stand No. 1")
),
ClientNamespacedWriteModel.insertOne<Any>(
namespace,
Document("name", "Kelly's Krepes")
)
)
val result = mongoClient
.bulkWrite(bulkOps, options)

Aunque la operación de escritura que inserta un documento con una clave duplicada genera un error, las demás operaciones se realizan porque la operación de escritura no está ordenada.

Para aprender a realizar operaciones de escritura individuales, consulte las siguientes guías:

  • Insertar documentos

  • Update Documents

  • Delete Documents

  • Reemplazar Documentos

Para obtener más información sobre cualquiera de los métodos o tipos discutidos en esta guía, consultar la siguiente documentación de la API:

Volver

Delete Documents