Operações em massa
Nesta página
Visão geral
Neste guia, você verá como usar o driver Rust para executar operações em massa.
As operações em massa executam múltiplas operações de gravação em um ou mais namespaces. Um namespace é uma combinação do nome do banco de dados de dados e do nome da coleção, no formato <database>.<collection>
. Como você executa operações em massa em uma instância do Client
, você pode executar operações em massa em qualquer namespace no cluster acessado pelo seu cliente.
Você pode executar operações em massa para reduzir o número de chamadas para o servidor. Em vez de enviar uma solicitação para cada operação, as operações em massa executam várias operações em uma ação.
Este guia inclui as seguintes seções:
Dados de amostra apresentam os dados de amostra que são usados pelos exemplos de operação em massa
Tipos de operação em massa descreve como utilizar tipos de
WriteModel
para executar operações de inserção, substituição, atualização e exclusão em massaTipo de Retorno descreve o valor de retorno do método
bulk_write()
e como acessar informações sobre a operação em massaModificar Comportamento descreve como modificar o comportamento padrão do método
bulk_write()
Gravar em namespaces mistos descreve como realizar uma operação em massa em vários namespaces em uma chamada de método
Informações adicionais fornecem links para recursos e documentação da API para os tipos e métodos mencionados neste guia
Importante
Para realizar operações de escrita em massa, certifique-se de que seu aplicação atenda aos seguintes requisitos:
Você está conectado à versão 8.0 do MongoDB Server ou posterior.
Você estiver usando o driver Rust versão 3.0 ou posterior.
Dados de amostra
Os exemplos deste guia usam os seguintes documentos de exemplo, que são armazenados na collection mushrooms
no banco de dados de dados db
:
let docs = vec![ doc! {"name" : "portobello", "color" : "brown", "edible" : true }, doc! {"name" : "chanterelle", "color" : "yellow", "edible" : true }, doc! {"name" : "oyster", "color" : "white", "edible" : true }, doc! {"name" : "fly agaric", "color" : "red", "edible" : false }, ];
Você também pode usar tipos de estrutura personalizados para representar seus dados de amostra. Para obter um exemplo que executa uma operação em massa usando Mushroom
estruturas para modelar os mesmos dados, consulte o exemplo de inserção de estruturas nesta página.
Tipos de operação em massa
Para executar uma operação de gravação em massa, passe uma array de WriteModel
instâncias de enumeração para o método bulk_write()
.
Nesta seção, você aprenderá a executar as seguintes operações de escrita em massa definindo seus tipos WriteModel
correspondentes:
Dica
Você também pode executar vários tipos de operações de gravação em uma única chamada de método bulk_write()
. Para visualizar um exemplo que passa um UpdateOneModel
e um InsertOneModel
para a mesma chamada bulk_write()
, consulte o exemplo Modificar comportamento neste guia.
Insert
Para executar uma operação de inserção em massa, crie uma instância InsertOneModel
para cada documento que você deseja inserir. Em seguida, passe uma lista de modelos para o método bulk_write()
.
A tabela a seguir descreve InsertOneModel
campos que você pode definir chamando seus métodos construtores correspondentes:
Campo | Descrição |
---|---|
namespace | The namespace on which the insert is performed. Type: Namespace |
document | The document to insert. Type: Document |
Exemplo de inserção de documentos
Este exemplo executa as seguintes ações:
Especifica duas instâncias do
InsertOneModel
em uma array. CadaInsertOneModel
representa um documento a ser inserido no namespacedb.mushrooms
.Passa a array de modelos para o método
bulk_write()
.Imprime o número de documentos inseridos.
let mushrooms: Collection<Document> = client.database("db").collection("mushrooms"); let models = vec![ InsertOneModel::builder() .namespace(mushrooms.namespace()) .document(doc! { "name": "lion's mane", "color": "white", "edible": true }) .build(), InsertOneModel::builder() .namespace(mushrooms.namespace()) .document(doc! { "name": "angel wing", "color": "white", "edible": false }) .build(), ]; let result = client.bulk_write(models).await?; println!("Inserted documents: {}", result.inserted_count);
Inserted documents: 2
Exemplo de inserção de estruturas
Você também pode modelar seus documentos usando structs e inserir instâncias de struct em massa no namespace db.mushrooms
.
Este exemplo executa a mesma operação que o exemplo de inserção de documentos anterior, mas insere instâncias do seguinte tipo de estrutura Mushroom
:
struct Mushroom { name: String, color: String, edible: bool, }
O código a seguir usa o método insert_one_model()
para construir uma instância InsertOneModel
a partir de cada instância Mushroom
e, em seguida, insere ambos os modelos em uma operação em massa:
let mushrooms: Collection<Mushroom> = client.database("db").collection("mushrooms"); let lions_mane = Mushroom { name: "lion's mane".to_string(), color: "white".to_string(), edible: true, }; let angel_wing = Mushroom { name: "angel wing".to_string(), color: "white".to_string(), edible: false, }; let lions_mane_model = mushrooms.insert_one_model(lions_mane)?; let angel_wing_model = mushrooms.insert_one_model(angel_wing)?; let result = client.bulk_write([lions_mane_model, angel_wing_model]).await?; println!("Inserted documents: {}", result.inserted_count);
Inserted documents: 2
Dica
Para saber mais sobre tipos de estrutura personalizada e serialização no driver Rust, consulte o guia sobre Modelagem e serialização de dados.
Substituir
Para executar uma operação de substituição em massa, crie uma instância ReplaceOneModel
para cada documento que deseja substituir. Em seguida, passe uma lista de modelos para o método bulk_write()
.
A tabela a seguir descreve ReplaceOneModel
campos que você pode definir chamando seus métodos construtores correspondentes:
Campo | Descrição |
---|---|
namespace | The namespace on which the operation is performed. Type: Namespace |
filter | The filter that matches the document you want to replace. Type: Document |
replacement | The replacement document. Type: Document |
collation | (Optional) The collation to use when sorting results. To learn more about collations,
see the Collations guide. Type: Document |
hint | (Optional) The index to use for the operation. To learn more about
indexes, see the Indexes guide. Type: Bson |
upsert | (Optional) Whether a new document is created if no document matches the filter. By default, this field is set to false .Type: bool |
Exemplo
Este exemplo executa as seguintes ações:
Especifica duas instâncias do
ReplaceOneModel
em uma array. As instânciasReplaceOneModel
contêm instruções para substituir documentos que representam Cogumelos no namespacedb.mushrooms
.Passa a array de modelos para o método
bulk_write()
.Imprime o número de documentos modificados.
let mushrooms: Collection<Document> = client.database("db").collection("mushrooms"); let models = vec![ ReplaceOneModel::builder() .namespace(mushrooms.namespace()) .filter(doc! { "name": "portobello" }) .replacement(doc! { "name": "cremini", "color": "brown", "edible": true }) .build(), ReplaceOneModel::builder() .namespace(mushrooms.namespace()) .filter(doc! { "name": "oyster" }) .replacement(doc! { "name": "golden oyster", "color": "yellow", "edible": true }) .upsert(true) .build(), ]; let result = client.bulk_write(models).await?; println!("Modified documents: {}", result.modified_count);
Modified documents: 2
Update
Para executar uma operação de atualização em massa, crie uma instância UpdateOneModel
ou UpdateManyModel
para cada atualização que você deseja fazer. Em seguida, passe uma lista de modelos para o método bulk_write()
. Um UpdateOneModel
atualiza somente um documento que corresponde a um filtro, enquanto um UpdateManyModel
atualiza todos os documentos que correspondem a um filtro.
A tabela seguinte descreve os campos UpdateOneModel
e UpdateManyModel
que você pode definir chamando seus métodos construtor correspondentes:
Campo | Descrição |
---|---|
namespace | The namespace on which the operation is performed. Type: Namespace |
filter | The filter that matches one or more documents you want to update. When specified in an UpdateOneModel ,
only the first matching document will be updated. When specified in an UpdateManyModel , all
matching documents will be updated.Type: Document |
update | The update to perform. Type: UpdateModifications |
array_filters | (Optional) A set of filters specifying which array elements an update applies to if you are updating an
array-valued field. Type: Array |
collation | (Optional) The collation to use when sorting results. To learn more about collations,
see the Collations guide. Type: Document |
hint | (Optional) The index to use for the operation. To learn more about
indexes, see the Indexes guide. Type: Bson |
upsert | (Optional) Whether a new document is created if no document matches the filter.
By default, this field is set to false .Type: bool |
Exemplo
Este exemplo executa as seguintes ações:
Especifica uma instância
UpdateOneModel
e uma instânciaUpdateManyModel
em uma array. Esses modelos contêm instruções para atualizar documentos representando Cogumelos no namespacedb.mushrooms
.Passa a array de modelos para o método
bulk_write()
.Imprime o número de documentos modificados.
let mushrooms: Collection<Document> = client.database("db").collection("mushrooms"); let models = vec![ WriteModel::UpdateOne( UpdateOneModel::builder() .namespace(mushrooms.namespace()) .filter(doc! { "name": "fly agaric" }) .update(doc! { "$set": { "name": "fly amanita" } }) .upsert(true) .build(), ), WriteModel::UpdateMany( UpdateManyModel::builder() .namespace(mushrooms.namespace()) .filter(doc! { "color": "yellow" }) .update(doc! { "$set": { "color": "yellow/orange" } }) .build(), ), ]; let result = client.bulk_write(models).await?; println!("Modified documents: {}", result.modified_count);
Modified documents: 2
Excluir
Para executar uma operação de exclusão em massa, crie uma instância DeleteOneModel
ou DeleteManyModel
para cada operação de exclusão. Em seguida, passe uma lista de modelos para o método bulk_write()
. Um DeleteOneModel
exclui apenas um documento que corresponde a um filtro, enquanto um DeleteManyModel
exclui todos os documentos que correspondem a um filtro.
A tabela seguinte descreve os campos DeleteOneModel
e DeleteManyModel
que você pode definir chamando seus métodos construtor correspondentes:
Campo | Descrição |
---|---|
namespace | The namespace on which the operation is performed. Type: Namespace |
filter | The filter that matches one or more documents you want to delete. When specified in a DeleteOneModel ,
only the first matching document will be deleted. When specified in a DeleteManyModel , all
matching documents will be deleted.Type: Document |
collation | (Optional) The collation to use when sorting results. To learn more about collations,
see the Collations guide. Type: Document |
hint | (Optional) The index to use for the operation. To learn more about
indexes, see the Indexes guide. Type: Bson |
Exemplo
Este exemplo executa as seguintes ações:
Especifica uma instância
DeleteOneModel
e uma instânciaDeleteManyModel
em uma array. Esses modelos contêm instruções para excluir documentos que representam Cogumelos no namespacedb.mushrooms
.Passa a array de modelos para o método
bulk_write()
.Imprime o número de documentos excluídos.
let mushrooms: Collection<Document> = client.database("db").collection("mushrooms"); let models = vec![ WriteModel::DeleteOne( DeleteOneModel::builder() .namespace(mushrooms.namespace()) .filter(doc! { "color": "red" }) .build(), ), WriteModel::DeleteMany( DeleteManyModel::builder() .namespace(mushrooms.namespace()) .filter(doc! { "edible": true }) .build(), ), ]; let result = client.bulk_write(models).await?; println!("Deleted documents: {}", result.deleted_count);
Deleted documents: 4
Tipo de devolução
O método bulk_write()
retorna uma instância de estrutura SummaryBulkWriteResult
da qual você pode acessar informações sobre sua operação em massa.
O tipo SummaryBulkWriteResult
tem os seguintes campos:
inserted_count
: o número de documentos inseridosmatched_count
: o número de documentos correspondentesmodified_count
: o número de documentos atualizadosupserted_count
: o número de documentos atualizadosdeleted_count
: o número de documentos excluídos
Você também pode utilizar o método verbose_results()
para visualizar informações detalhadas sobre cada operação. O método verbose_results()
retorna uma instância de estrutura VerboseBulkWriteResult
, que tem os seguintes campos:
delete_results
: os resultados de cada operação de exclusão bem-sucedidainsert_results
: os resultados de cada operação de inserção bem-sucedidaupdate_results
: os resultados de cada operação de atualização bem-sucedidasummary
: um resumo dos resultados de cada tipo de operação
O exemplo a seguir encadeia o método verbose_results()
ao método bulk_write()
e imprime os resultados das operações de atualização e exclusão:
let models = vec![ WriteModel::DeleteOne( DeleteOneModel::builder() .namespace(mushrooms.namespace()) .filter(doc! { "name": "oyster" }) .build(), ), WriteModel::UpdateOne( UpdateOneModel::builder() .namespace(mushrooms.namespace()) .filter(doc! { "name": "chanterelle" }) .update(doc! { "$set": { "season": ["July", "August", "September"] } }) .build(), ), ]; let result = client.bulk_write(models).verbose_results().await?; println!( "Update results: {:?}\nDelete results: {:?}\n", result.update_results, result.delete_results );
Update results: {1: UpdateResult { matched_count: 1, modified_count: 1, upserted_id: None }} Delete results: {0: DeleteResult { deleted_count: 1 }}
Modificar comportamento
Você pode modificar o comportamento do método bulk_write()
definindo os valores do campo BulkWriteOptions
. Para definir esses campos de estrutura, encadeie os métodos correspondentes dos campos ao método bulk_write()
.
A estrutura BulkWriteOptions
contém os seguintes campos:
Campo | Descrição | Valor padrão |
---|---|---|
ordered | Whether the operations run in the order in which they were specified. When set to true , one failed operation prevents subsequent operations from running.When set to false , the server continues to attempt write operations if one fails.Type: bool | true |
bypass_document_validation | Whether document-level validation is bypassed. Type: bool | false |
comment | An arbitrary comment to help trace the operation through the database profiler, currentOp,
and logs. Type: Bson | None |
let_vars | A map of parameter names and values to apply to all operations within the bulk write.
Values must be constant or closed expressions that do not reference document fields. Type: Document | None |
write_concern | The write concern to use for this bulk operation. Type: WriteConcern | Herda a preocupação de gravação do namespace |
Exemplo
Este exemplo tenta executar operações de atualização e inserir na coleção mushrooms
. O código a seguir define o campo ordered
como false
encadeando o método ordered()
ao método bulk_write()
:
let mushrooms: Collection<Document> = client.database("db").collection("mushrooms"); let models = vec![ WriteModel::UpdateOne(UpdateOneModel::builder() .namespace(mushrooms.namespace()) .filter(doc! { "name": "portobello" }) .update(doc! { "$set": { "_id": 123 } }) .upsert(true) .build()), WriteModel::InsertOne(InsertOneModel::builder() .namespace(mushrooms.namespace()) .document(doc! { "name": "reishi", "color": "red/brown", "edible": true }) .build()), ]; let result = client.bulk_write(models).ordered(false).await?; println!( "Inserted documents: {}\nDeleted documents: {}", result.inserted_count, result.deleted_count );
Error: Error { kind: BulkWrite(BulkWriteError { write_concern_errors: [], write_errors: {0: WriteError { code: 66, code_name: None, message: "Plan executor error during update :: caused by :: Performing an update on the path '_id' would modify the immutable field '_id'", details: None }}, partial_result: Some(Summary(SummaryBulkWriteResult { inserted_count: 1, matched_count: 0, modified_count: 0, upserted_count: 0, deleted_count: 0 })) }), labels: ... }
O campo _id
é imutável e não pode ser alterado em uma operação de atualização. Como o UpdateOneModel
inclui instruções para atualizar este campo, a operação em massa retorna um BulkWriteError
e executa somente a operação de inserção. Se você definir o campo ordered
como true
, o driver não tentará nenhuma operação subsequente após a operação de atualização malsucedida e o driver não inserirá nenhum documento.
Escrever em namespaces mistos
Os exemplos anteriores nesta página executam operações em massa no namespace do db.mushrooms
. No entanto, você pode realizar gravações em massa em vários namespaces em uma única chamada de método.
O exemplo a seguir insere um documento no namespace ingredients.sweet
e um documento no namespace meals.dessert
:
let sweet: Collection<Document> = client .database("ingredients") .collection("sweet"); let dessert: Collection<Document> = client .database("meals") .collection("dessert"); let models = vec![ InsertOneModel::builder() .namespace(sweet.namespace()) .document(doc! { "name": "brown sugar", "price": 3.99 }) .build(), InsertOneModel::builder() .namespace(dessert.namespace()) .document(doc! { "name": "banana bread", "cook_time": 75 }) .build(), ]; let result = client.bulk_write(models).await?; println!("Inserted documents: {}", result.inserted_count);
Inserted documents: 2
Informações adicionais
Para saber mais sobre operações em massa, consulte Operações de Gravação em Massa no manual do Servidor.