Operações em massa
Nesta página
Visão geral
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 .
Gravação em massa de collections
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( 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:
Inserir operação
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.
Exemplo
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.
Operação de substituição
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.
Exemplo
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:
Documentação da API doReplaceOneModel
Documentaçãoda API ReplaceOptions
Referência deíndices exclusiva no manual do servidor
Operação de atualização
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.
Exemplo
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:
UpdateOneModel API documentation
Documentação da API doUpdateManyModel
UpdateOptions API documentation
Explicação do manual do servidor de índices exclusivos
Excluir operação
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.
Exemplo
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:
Ordem de execução
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.
Execução ordenada
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.
Exemplo
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 oage
é37
Uma operação de substituição para um documento onde o
_id
é1
por um novo documento que contém o campolocation
Uma operação de atualização para um documento onde o
_id
é6
para alterar o camponame
Uma operação de exclusão para todos os documentos que têm um valor de
age
maior que50
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 }
Execução não ordenada
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:
Gravação em massa do cliente
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 |
---|---|---|---|
|
| Cria um modelo para inserir um documento no |
|
|
| Cria um modelo para atualizar o primeiro documento no |
Você deve passar um valor para o parâmetro |
|
| Cria um modelo para atualizar todos os documentos no |
Você deve passar um valor para o parâmetro |
|
| Cria um modelo para substituir o primeiro documento no |
|
|
| Cria um modelo para excluir o primeiro documento no |
|
|
| Cria um modelo para excluir todos os documentos no |
|
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( val id: Int, val name: String, ) data class Object( 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:
Inserir operação
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)
Operação de substituição
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.
Opções de gravação em massa
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.
Ordem de execução
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:
Resumo
MongoCollection.bulkWrite()
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 .
MongoClient.bulkWrite()
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 .