Visão geral
Neste guia, você pode aprender como usar operações em massa no MongoDB Kotlin Driver.
Para operações CRUD individuais, você pode usar o método relevante. Por exemplo, para inserir um documento e atualizar vários documentos, você pode usar o método insertOne()
e o método updateMany()
.
O MongoClient
executa estas operações fazendo uma solicitação ao reconhecimento de data center correspondente a cada operação. Você pode reduzir o número de chamadas para o reconhecimento de data center usando operações em massa.
Execução de operações em massa
As operações em massa consistem em um grande número de operações de escrita. Para executar uma operação em massa, passe um List
contendo WriteModel
documentos para o método bulkWrite()
. Um WriteModel
é um modelo que representa uma única operação de gravação.
As seções a seguir mostram como criar e usar cada variação do tipo WriteModel
. Os exemplos em cada seção utilizam os seguintes documento na collection 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 com a seguinte classe de dados 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)
Para obter mais informações sobre os métodos e classes descritas nesta seção, consulte os seguintes recursos:
Documentação da API do ReplaceOneModel
Índices exclusivos Explicação do 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)
Para obter mais informações sobre os métodos e classes descritas nesta seção, consulte os seguintes recursos:
Documentação da API do UpdateOneModel
Documentação da API do UpdateManyModel
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:
Resumo
Para executar uma operação em massa, crie e passe uma lista de documentos do WriteModel
para o método bulkWrite()
.
Existem seis variações de WriteModel
:
InsertOneModel
ReplaceOneModel
UpdateOneModel
UpdateManyModel
DeleteOneModel
DeleteManyModel
Há duas maneiras de executar o método bulkWrite()
:
Solicitado, onde o driver executa as operações de gravação para ocorrer qualquer erro
Não ordenado, onde o driver executa todas as operações de gravação em qualquer ordem e relata quaisquer erros após a conclusão das operações