Docs Menu
Docs Home
/ /

Operaciones masivas

En esta guía, puede aprender a utilizar operaciones masivas en el controlador Kotlin.

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 tu aplicación se conecta a MongoDB servidor versión 8.0 o posterior, puedes utilizar el método MongoClient.bulkWrite() para realizar operaciones de escritura en bloque en varias colecciones y bases de datos dentro del mismo clúster. Este método realiza todas las operaciones de guardar en una sola llamada a la base de datos.

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 }

Estos datos están modelados por la siguiente clase de datos de Kotlin:

data class Person(
@BsonId val id: Int,
val name: String,
val age: Int? = null,
val location: String? = null
)

Para obtener más información sobre los métodos y clases mencionados en esta sección, consulte la siguiente documentación de API:

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.

El siguiente ejemplo crea un InsertOneModel para dos documentos que describen personas:

val juneDoc = InsertOneModel(Person(3, "June Carrie", 17))
val kevinDoc = InsertOneModel(Person(4, "Kevin Moss", 22))

Importante

Al realizar una operación bulkWrite(), el InsertOneModel no puede insertar un documento con un _id ya existente en la colección. En este caso, el controlador lanza un MongoBulkWriteException.

El siguiente ejemplo intenta insertar dos documentos donde los valores _id son 1 y 3. Dado que ya existe un documento con un valor _id o 1 en la colección, la operación genera un error:

try {
val bulkOperations = listOf(
(InsertOneModel(Person(1, "James Smith", 13))),
(InsertOneModel(Person(3, "Colin Samuels")))
)
val bulkWrite = collection.bulkWrite(bulkOperations)
} catch (e: MongoBulkWriteException) {
println("A MongoBulkWriteException occurred with the following message: " + e.message)
}
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 saber por qué el controlador no insertó el documento con el _id 3de, 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.

Para realizar una operación de reemplazo, cree un ReplaceOneModel especificando un filtro de consulta para el documento que desea reemplazar y el documento de reemplazo.

Importante

Al ejecutar un bulkWrite(), el ReplaceOneModel no puede realizar cambios que infrinjan las restricciones de índice único de la colección. Además, el modelo no realiza la operación de reemplazo si no hay coincidencias con el filtro de consulta.

El siguiente ejemplo crea un ReplaceOneModel para reemplazar un documento donde el _id es 1 con un documento que contiene el campo adicional location:

val filter = Filters.eq("_id", 1)
val insert = Person(1, "Celine Stork", location = "San Diego, CA")
val doc = ReplaceOneModel(filter, insert)

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("_id"))

Para obtener más información sobre los métodos y clases mencionados en esta sección, consulte los siguientes recursos:

Para realizar una operación de actualización, cree un UpdateOneModel o un UpdateManyModel que especifique un filtro de consulta y un documento de actualización.

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 una consulta bulkWrite(), los tipos UpdateOneModel y UpdateManyModel no pueden realizar cambios que infrinjan las restricciones de índice único de la colección. Además, los modelos no realizan operaciones de actualización si no hay coincidencias con el filtro de consulta.

El siguiente ejemplo crea un UpdateOneModel para incrementar el campo age en 1 en un documento donde el _id es 2:

val filter = Filters.eq("_id", 2)
val update = Updates.inc(Person::age.name, 1)
val doc = UpdateOneModel<Person>(filter, update)

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("_id"))

Para obtener más información sobre los métodos y clases mencionados en esta sección, consulte los siguientes recursos:

Para realizar una operación de eliminación, cree un DeleteOneModel o un DeleteManyModel que especifique un filtro de query 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 realizar una bulkWrite(), los tipos DeleteOneModel y DeleteManyModel no eliminan ningún documento si no hay coincidencias con el filtro de consulta.

El siguiente ejemplo crea un DeleteOneModel para eliminar un documento donde el _id es 1 y un DeleteManyModel para eliminar documentos donde el valor age es menor que 30:

val deleteId1 = DeleteOneModel<Person>(Filters.eq("_id", 1))
val deleteAgeLt30 = DeleteManyModel<Person>(Filters.lt(Person::age.name, 30))

Para obtener más información sobre los métodos y clases mencionados en esta sección, consulte la siguiente documentación de API:

El método bulkWrite() acepta un BulkWriteOptions opcional como segundo parámetro para especificar si desea ejecutar las operaciones masivas de forma ordenada o desordenada.

De forma predeterminada, el método bulkWrite() ejecuta las operaciones masivas en orden. Esto significa que las operaciones se ejecutan en el orden en que se añadieron a la lista hasta que se produzca algún error.

El siguiente ejemplo realiza estas operaciones masivas:

  • Una operación de inserción para un documento donde name es "Zaynab Omar" y age es 37

  • Una operación de reemplazo para un documento donde _id es 1 con un nuevo documento que contiene el campo location

  • Una operación de actualización para un documento donde _id es 6 para cambiar el campo name

  • Una operación de eliminación para todos los documentos que tengan un valor age mayor que 50

val insertMdl = InsertOneModel(Person(6, "Zaynab Omar", 37))
val replaceMdl = ReplaceOneModel(
Filters.eq("_id", 1),
Person(1, "Sandy Kane", location = "Helena, MT")
)
val updateMdl = UpdateOneModel<Person>(
Filters.eq("_id", 6),
Updates.set(Person::name.name, "Zaynab Hassan")
)
val deleteMdl = DeleteManyModel<Person>(Filters.gt(Person::age.name, 50))
val bulkOperations = listOf(
insertMdl,
replaceMdl,
updateMdl,
deleteMdl
)
val result = 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 }

También puede ejecutar operaciones masivas en cualquier orden pasando false al método ordered() de un objeto BulkWriteOptions. Esto significa que todas las operaciones de escritura se ejecutan independientemente de los errores. Si se produce algún error, el controlador lo informa al final.

El siguiente código muestra cómo ejecutar una operación masiva sin orden de ejecución:

val options = BulkWriteOptions().ordered(false)
val unorderedResult = 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() realizó la operación de inserción después de la operación de actualización, esta no produciría cambios porque el documento no existía en ese momento. La colección contendría 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:

Al conectarse a una implementación con el servidor MongoDB 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

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 ofrecen ejemplos de cómo usar el método cliente bulkWrite(). Los datos de ejemplo se modelan mediante las siguientes clases de datos de Kotlin:

data class Person(
@BsonId val id: Int,
val name: String,
val age: Int? = null,
)
data class Object(
@BsonId val id: Int,
val type: String,
val category: String? = null,
val manufacturer: String? = null,
)

Para obtener más información sobre los métodos y clases mencionados en esta sección, consulte la siguiente documentación de API:

Este ejemplo muestra cómo usar el método bulkWrite() para insertar dos documentos. Un documento se inserta en la colección sample_db.people y el otro en la colección sample_db.objects. La instancia MongoNamespace define las bases de datos y colecciones a las que se aplica cada operación de escritura.

val docsToInsert = mutableListOf<ClientNamespacedWriteModel>()
docsToInsert.add(
ClientNamespacedWriteModel
.insertOne(
MongoNamespace("sample_db", "people"),
Person(2, "Julia Smith")
)
)
docsToInsert.add(
ClientNamespacedWriteModel
.insertOne(
MongoNamespace("sample_db", "objects"),
Object(2, "washing machine")
)
)
val clientBulkResult = client.bulkWrite(docsToInsert)

El siguiente ejemplo muestra cómo utilizar el método bulkWrite() para actualizar documentos existentes en las colecciones sample_db.people y sample_db.objects:

val docsToInsert = mutableListOf<ClientNamespacedWriteModel>()
docsToInsert.add(
ClientNamespacedWriteModel
.updateOne(
MongoNamespace("sample_db", "people"),
Filters.eq(Person::name.name, "Freya Polk"),
Updates.inc(Person::age.name, 1)
)
)
docsToInsert.add(
ClientNamespacedWriteModel
.updateMany(
MongoNamespace("sample_db", "objects"),
Filters.eq(Object::category.name, "electronic"),
Updates.set(Object::manufacturer.name, "Premium Technologies")
)
)
val clientBulkResult = client.bulkWrite(docsToInsert)

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 objects.

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 utilizar el método bulkWrite() para reemplazar documentos existentes en las colecciones sample_db.people y sample_db.objects.

val docsReplacements = mutableListOf<ClientNamespacedWriteModel>()
docsReplacements.add(
ClientNamespacedWriteModel
.replaceOne(
MongoNamespace("sample_db", "people"),
Filters.eq(Person::id.name, 1),
Person(1, "Frederic Hilbert")
)
)
docsReplacements.add(
ClientNamespacedWriteModel
.replaceOne(
MongoNamespace("sample_db", "objects"),
Filters.eq(Object::id.name, 1),
Object(1, "ironing board")
)
)
val clientBulkResult = client.bulkWrite(docsReplacements)

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 objects 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:

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

Puede pasar una instancia de ClientBulkWriteOptions al método bulkWrite() para especificar opciones al ejecutar las operaciones de escritura masiva.

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.

val namespace = MongoNamespace("sample_db", "people")
val options = ClientBulkWriteOptions
.clientBulkWriteOptions()
.ordered(false)
val bulkOperations = listOf(
ClientNamespacedWriteModel.insertOne(
namespace,
Person(2, "Rudra Suraj")
),
// Causes duplicate key error
ClientNamespacedWriteModel.insertOne(
namespace,
Person(2, "Wendy Zhang")
),
ClientNamespacedWriteModel.insertOne(
namespace,
Person(4, "Mario Bianchi")
)
)
val result = client.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.

Para obtener más información sobre los métodos y clases mencionados en esta sección, consulte la siguiente documentación de API:

Para realizar una operación masiva, crea y pasa una lista de WriteModel instancias al método bulkWrite().

Hay 6 subtipos diferentes de WriteModel: InsertOneModel, ReplaceOneModel, UpdateOneModel, UpdateManyModel, DeleteOneModel y DeleteManyModel.

Hay dos formas de ejecutar el método bulkWrite():

  • Ordenado, que realiza las operaciones en masa en orden hasta que se produzca un error, si lo hay

  • Desordenado, que realiza todas las operaciones en masa en cualquier orden e informa errores al final, si los hay

Para obtener más información sobre el comando de colección,bulkWrite consulte la referencia del método db.collection.bulkWrite() en el Manual del servidor MongoDB.

Al conectarse a una implementación que ejecuta la versión de servidor MongoDB 8.0 o posterior, puede usar el método MongoClient.bulkWrite() para realizar operaciones masivas en varias bases de datos y colecciones a la vez.

Para realizar una operación masiva de cliente, crea y pasa una lista de ClientNamespacedWriteModel instancias a este método.

Existen seis subtipos de ClientNamespacedWriteModel que se utilizan para representar operaciones de escritura. Para construir estos modelos de escritura, se pueden usar los métodos ClientNamespacedWriteModel correspondientes: insertOne(), updateOne(), updateMany(), replaceOne(), deleteOne() y deleteMany(). Estos métodos toman un objeto MongoNamespace que define en qué base de datos y colección se escribirá.

El método MongoClient.bulkWrite() también puede tomar un objeto ClientBulkWriteOptions para especificar diferentes opciones sobre cómo se ejecuta el comando.

Para aprender más sobre el comando de cliente bulkWrite, consulta la referencia del método bulkWrite() en el Manual del servidor de MongoDB.

Volver

Delete Documents

En esta página