Menu Docs
Página inicial do Docs
/ / /
Kotlin Coroutine
/ / /

Operações em massa

Nesta página

  • Visão geral
  • Gravação em massa de collections
  • Inserir operação
  • Operação de substituição
  • Operação de atualização
  • Excluir operação
  • Ordem de execução
  • Gravação em massa do cliente
  • Inserir operação
  • Operação de substituição
  • Opções de gravação em massa
  • Resumo
  • MongoCollection.bulkWrite()
  • MongoClient.bulkWrite()

Neste guia, você pode aprender como usar as operações em massa no driver Kotlin .

Para executar uma única operação de criação, substituição, atualização ou exclusão, você pode usar o método correspondente. Por exemplo, para inserir um documento e substituir um documento, você pode usar os métodos insertOne() e replaceOne(). Ao usar esses métodos, seu cliente faz uma chamada ao banco de dados para cada operação.

Ao usar uma operação de gravação em massa, você pode executar várias operações de gravação em menos chamadas de banco de dados . Você pode realizar operações de gravação em massa nos seguintes níveis:

  • Collection: você pode usar o MongoCollection.bulkWrite() método para executar operações de escrita em massa em uma única collection. Nesse método, cada tipo de operação de gravação requer pelo menos uma chamada de banco de dados . Por exemplo, MongoCollection.bulkWrite() coloca várias operações de atualização em uma chamada, mas faz duas chamadas separadas para o banco de dados para uma operação de inserção e uma operação de substituição.

  • Cliente: se o seu aplicação se conectar à versão do servidor MongoDB 8.0 ou posterior, você poderá usar o MongoClient.bulkWrite() método para executar operações de gravação em massa em várias coleções e bancos de dados no mesmo cluster. Este método executa todas as operações de gravação em uma chamada de banco de dados .

As operações de gravação em massa contêm uma ou mais operações de gravação. Para executar uma operação de gravação em massa no nível da coleção, passe um List de WriteModel documentos para o método MongoCollection.bulkWrite(). Um WriteModel é um modelo que representa uma operação de gravação.

O método MongoCollection.bulkWrite() executa cada tipo de operação de gravação em uma chamada de banco de dados separada. Por exemplo, quando você passa DeleteOneModel, DeleteManyModel e ReplaceOneModel objetos para o método, ele executa duas chamadas: uma para as operações de exclusão e outra para a operação de substituição.

Observação

Quando o cliente divide as operações em chamadas de banco de dados separadas, ele pode reordenar as operações para obter maior eficiência se a operação de gravação em massa não for ordenada. Para saber mais sobre a ordem de execução da operação, consulte a seção Ordem de execução.

As seções a seguir mostram como criar e usar cada documento WriteModel. Os exemplos em cada seção utilizam os seguintes documentos na coleção people:

{ "_id": 1, "name": "Karen Sandoval", "age": 31 }
{ "_id": 2, "name": "William Chin", "age": 54 }
{ "_id": 8, "name": "Shayla Ray", "age": 20 }

Esses dados são modelados pela seguinte classe de dados de Kotlin :

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

Para obter mais informações sobre os métodos e as classes mencionadas nesta seção, consulte a seguinte documentação da API:

Para executar uma operação de inserção, crie um InsertOneModel especificando o documento que você deseja inserir. Para inserir vários documentos, você deve criar um InsertOneModel para cada documento que deseja inserir.

O exemplo abaixo cria um InsertOneModel para dois documentos descrevendo pessoas:

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

Importante

Ao executar uma operação bulkWrite() , o InsertOneModel não pode inserir um documento com um _id que já existe na coleção. Nesse caso, o driver lança um MongoBulkWriteException.

O exemplo a seguir tenta inserir dois documentos onde os valores de _id são 1 e 3. Como já existe um documento com um _id de 1 na collection, a operação resulta em um erro:

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 que o driver não inseriu o documento com o _id de 3, consulte a seção Ordem de Execução .

Para obter mais informações sobre os métodos e as classes mencionados nesta seção, consulte a documentação da API InsertOneModel.

Para executar uma operação de substituição, crie um ReplaceOneModel especificando um filtro de query para o documento que você deseja substituir e o documento de substituição.

Importante

Ao executar uma bulkWrite(), o ReplaceOneModel não pode fazer alterações que violem restrições de índice únicas na collection. Além disso, o modelo não executa a operação de substituição se não houver correspondência com o filtro de query.

O exemplo a seguir cria um ReplaceOneModel para substituir um documento onde o _id é 1 por um documento que contém o campo location adicional:

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

Se vários documentos corresponderem ao filtro de query especificado na instância ReplaceOneModel, a operação substituirá o primeiro resultado. Você pode especificar uma classificação em uma instância do ReplaceOptions para aplicar um pedido aos documentos correspondentes antes que o driver execute a operação de substituição, conforme mostrado no código a seguir:

val opts = ReplaceOptions().sort(Sorts.ascending("_id"))

Para obter mais informações sobre os métodos e classes descritas nesta seção, consulte os seguintes recursos:

Para executar uma operação de atualização, crie um UpdateOneModel ou um UpdateManyModel que especifique um filtro de query e um documento de atualização.

O UpdateOneModel atualiza o primeiro documento que corresponde ao seu filtro de query, e o UpdateManyModel atualiza todos os documentos que correspondem ao seu filtro de query.

Importante

Ao executar um bulkWrite(), os tipos UpdateOneModel e UpdateManyModel não podem fazer alterações que violem o índice único na collection. Além disso, os modelos não executam operações de atualização se não houver correspondência com o filtro de query.

O exemplo a seguir cria um UpdateOneModel para incrementar o campo age em 1 em um documento onde o _id é 2:

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

Se vários documentos corresponderem ao filtro de query especificado na instância UpdateOneModel, a operação atualizará o primeiro resultado. Você pode especificar uma classificação em uma instância do UpdateOptions para aplicar um pedido aos documentos correspondentes antes que o driver execute a operação de atualização, conforme mostrado no código a seguir:

val opts = UpdateOptions().sort(Sorts.ascending("_id"))

Para obter mais informações sobre os métodos e classes descritas nesta seção, consulte os seguintes recursos:

Para executar uma operação de exclusão, crie um DeleteOneModel ou um DeleteManyModel que especifique um filtro de query para documentos que você deseja excluir.

O DeleteOneModel exclui o primeiro documento que corresponde ao filtro de query e o DeleteManyModel exclui todos os documentos que correspondem ao filtro de query.

Importante

Ao executar um bulkWrite(), os tipos DeleteOneModel e DeleteManyModel não excluem nenhum documento se não houver correspondência com o filtro de query.

O exemplo a seguir cria um DeleteOneModel para excluir um documento onde o _id é 1 e um DeleteManyModel para excluir documentos onde o valor age é menor que 30:

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

Para obter mais informações sobre os métodos e as classes mencionadas nesta seção, consulte a seguinte documentação da API:

O método bulkWrite() aceita um BulkWriteOptions opcional como segundo parâmetro para especificar se você deseja executar as operações em massa como ordenadas ou não.

Por padrão, o método bulkWrite() executa operações em massa em ordem. Isso significa que as operações são executadas na ordem em que você as adicionou à lista até que ocorra um erro.

O exemplo a seguir executa estas operações em massa:

  • Uma operação de inserção para um documento onde o name é "Zaynab Omar" e o age é 37

  • Uma operação de substituição para um documento onde o _id é 1 por um novo documento que contém o campo location

  • Uma operação de atualização para um documento onde o _id é 6 para alterar o campo name

  • Uma operação de exclusão para todos os documentos que têm um valor de age maior 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)

Depois de executar este exemplo, sua collection conterá o seguinte documento:

{ "_id": 1, "name": "Sandy Kane", "location": "Helena, MT" }
{ "_id": 8, "name": "Shayla Ray", "age": 20 }
{ "_id": 6, "name": "Zaynab Hassan", "age": 37 }

Você também pode executar operações em massa em qualquer ordem, passando false para o método ordered() em um objeto BulkWriteOptions . Isso significa que todas as operações de gravação são executadas independentemente de erros. Se ocorrerem erros, o driver os relata no final.

O seguinte código mostra como executar uma operação em massa sem ordem de execução:

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

Observação

As operações em bloco não ordenadas não garantem a ordem de execução. A ordem pode ser diferente da forma como você as lista para otimizar o tempo de execução.

No exemplo anterior, se o método bulkWrite() executasse a operação de inserção após a operação de atualização, a operação de atualização não produziria alterações porque o documento não existia naquele momento. A collection conteria então os seguintes documento:

{ "_id": 1, "name": "Sandy Kane", "location": "Helena, MT" }
{ "_id": 8, "name": "Shayla Ray", "age": 20 }
{ "_id": 6, "name": "Zaynab Omar", "age": 37 }

Para obter mais informações sobre os métodos e as classes mencionadas nesta seção, consulte a seguinte documentação da API:

Ao conectar a um sistema executando o servidor MongoDB 8.0 ou posterior, você pode usar o método MongoClient.bulkWrite() para escrever em vários bancos de dados e collections no mesmo cluster. O método MongoClient.bulkWrite() executa todas as operações de gravação em uma única chamada.

O método MongoClient.bulkWrite() usa uma lista de instâncias do ClientNamespacedWriteModel para representar diferentes operações de gravação. Você pode construir instâncias da interface ClientNamespacedWriteModel utilizando métodos de instância. Por exemplo, uma instância de ClientNamespacedInsertOneModel representa uma operação para inserir um documento e você pode criar esse modelo usando o método ClientNamespacedWriteModel.insertOne().

Observação

Erros de gravação em massa

Se qualquer uma das operações de gravação falhar, o driver emitirá um ClientBulkWriteException e não executará mais nenhuma operação individual. ClientBulkWriteException inclui um BulkWriteError que pode ser acessado usando o método ClientBulkWriteException.getWriteErrors() , que fornece detalhes da falha individual.

Os modelos e seus métodos de instância correspondentes são descritos na tabela abaixo.

Modelo
Método de instância
Descrição
Parâmetros

ClientNamespacedInsertOneModel

insertOne()

Cria um modelo para inserir um documento no namespace.

namespace: Banco de dados e coleção para escrever em

document: Documento a inserir

ClientNamespacedUpdateOneModel

updateOne()

Cria um modelo para atualizar o primeiro documento no namespace que corresponde a filter.

namespace: Banco de dados e coleção para escrever em

filter: Filtro que seleciona qual documento atualizar

update: Atualize para aplicar ao documento correspondente

updatePipeline: Atualize o pipeline para aplicar ao documento correspondente

options: (opcional) Opções a serem aplicadas ao atualizar o documento

Você deve passar um valor para o parâmetro update ou updatePipeline.

ClientNamespacedUpdateManyModel

updateMany()

Cria um modelo para atualizar todos os documentos no namespace que correspondem a filter.

namespace: Banco de dados e coleção para escrever em

filter: Filtro que seleciona quais documentos atualizar

update: Atualize para aplicar aos documentos correspondentes

updatePipeline: Atualize o pipeline para aplicar aos documentos correspondentes

options: (opcional) Opções a serem aplicadas ao atualizar documentos

Você deve passar um valor para o parâmetro update ou updatePipeline.

ClientNamespacedReplaceOneModel

replaceOne()

Cria um modelo para substituir o primeiro documento no namespace que corresponde a filter.

namespace: Banco de dados e coleção para escrever em

filter: Filtro que seleciona qual documento substituir

replacement: documento de substituição

options: (opcional) Opções a serem aplicadas ao substituir documentos

ClientNamespacedDeleteOneModel

deleteOne()

Cria um modelo para excluir o primeiro documento no namespace que corresponde a filter.

namespace: Banco de dados e coleção para escrever em

filter: Filtro que seleciona qual documento excluir

option: (opcional) Opções a serem aplicadas ao excluir o documento

ClientNamespacedDeleteManyModel

deleteMany()

Cria um modelo para excluir todos os documentos no namespace que correspondem a filter.

namespace: Banco de dados e coleção para escrever em

filter: Filtro que seleciona quais documentos excluir

option: (opcional) Opções a serem aplicadas ao excluir documentos

As seções seguintes fornecem exemplos de como utilizar o método do cliente bulkWrite(). Os dados de amostra são modelados pelas seguintes classes de dados de Kotlin :

data class Person(
@BsonId val id: Int,
val name: String,
)
data class Object(
@BsonId val id: Int,
val type: String,
)

Para saber mais sobre os métodos e as classes mencionadas nesta seção, consulte a seguinte documentação da API:

Este exemplo mostra como usar o método bulkWrite() para inserir dois documentos. Um documento é inserido na collection sample_db.people, enquanto o outro documento é inserido na collection sample_db.objects. A instância MongoNamespace define os bancos de dados e as collections aos quais cada operação de gravação se aplica.

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)

O exemplo a seguir mostra como usar o método bulkWrite() para substituir documentos existentes nas coleções sample_db.people e sample_db.things.

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)

Depois que esse exemplo for executado com êxito, o documento que tem um valor _id de 1 na coleção people é substituído por um novo documento. O documento na coleção things que tem um valor _id de 1 é substituído por um novo documento.

Você pode passar uma instância de ClientBulkWriteOptions para o método bulkWrite() para especificar opções ao executar operações de gravação em massa.

Por padrão, as operações individuais em uma operação em massa são executadas na ordem em que você as especifica até que ocorra um erro ou até que sejam executadas com êxito. No entanto, você pode passar false para o método ordered() na interface ClientBulkWriteOptions para executar operações de gravação de forma não ordenada. Ao usar a opção não ordenada, uma operação de produção de erro não impede a execução de outras operações de gravação na chamada para o método bulkWrite().

O código a seguir define o método ordered() em uma instância de ClientBulkWriteOptions e executa uma operação de gravação em massa para inserir vários 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)

Embora a operação de gravação que insere um documento com uma chave duplicada resulte em um erro, as outras operações são executadas porque a operação de gravação não é ordenada.

Para saber mais sobre os métodos e as classes mencionadas nesta seção, consulte a seguinte documentação da API:

Para executar uma operação em massa, você cria e passa uma lista de instâncias do WriteModel para o método bulkWrite().

Existem 6 subtipos diferentes de WriteModel: InsertOneModel, ReplaceOneModel, UpdateOneModel, UpdateManyModel, DeleteOneModel e DeleteManyModel.

Há duas maneiras de executar o método bulkWrite():

  • Solicitado, que executa as operações em massa para que ocorra um erro, se houver

  • Não ordenado, que executa todas as operações em massa em qualquer ordem e relata erros no final, se houver

Para saber mais sobre o bulkWrite comando da coleção, consulte a referência do método db.collection.bulkWrite() no Manual do servidor MongoDB .

Ao conectar a um sistema executando o servidor MongoDB versão 8.0 ou posterior, você pode usar o método MongoClient.bulkWrite() para executar operações em massa em vários bancos de dados e collections de uma só vez.

Para executar uma operação em massa do cliente , você cria uma lista de ClientNamespacedWriteModel instâncias para este método.

Há seis subtipos de ClientNamespacedWriteModel usados para representar operações de escrita. Para construir esses modelos de gravação, você pode usar os métodos ClientNamespacedWriteModel correspondentes insertOne(), updateOne(), updateMany(), replaceOne(), deleteOne() e deleteMany(). Esses métodos usam um objeto MongoNamespace que define em qual banco de dados e coleção escrever.

O método MongoClient.bulkWrite() também pode usar um objeto ClientBulkWriteOptions para especificar diferentes opções de como o comando é executado.

Para saber mais sobre o comando do cliente,bulkWrite consulte a referência do método bulkWrite() no Manual do servidor MongoDB .

Voltar

Inserir ou atualizar em uma única operação