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
WriteModelpara 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 |
|---|---|
| O namespace no qual a inserção é executada. |
| O documento a inserir. |
Exemplo de inserção de documentos
Este exemplo executa as seguintes ações:
Especifica duas instâncias do
InsertOneModelem uma array. CadaInsertOneModelrepresenta 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 personalizados 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 |
|---|---|
| O namespace no qual a operação é executada. |
| O filtro que corresponde ao documento que você deseja substituir. |
| O documento de substituição. |
| (Opcional) O agrupamento a ser usado ao classificar os resultados. Para saber mais sobre agrupamentos, consulte o guia Agrupamentos. |
| (Opcional) O índice a ser usado para a operação. Para aprender mais sobre índice, consulte o guia Índices . |
| (Opcional) Se um novo documento será criado se nenhum documento corresponder ao filtro. |
Exemplo
Este exemplo executa as seguintes ações:
Especifica duas instâncias do
ReplaceOneModelem uma array. As instânciasReplaceOneModelcontê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 |
|---|---|
| O namespace no qual a operação é executada. |
| O filtro que corresponde a um ou mais documentos que você deseja atualizar. Quando especificado em um |
| A atualização a ser executada. |
| (Opcional) Um conjunto de filtros que especificam a quais elementos de array uma atualização se aplica se você estiver atualizando um campo com valor de array. |
| (Opcional) O agrupamento a ser usado ao classificar os resultados. Para saber mais sobre agrupamentos, consulte o guia Agrupamentos. |
| (Opcional) O índice a ser usado para a operação. Para aprender mais sobre índice, consulte o guia Índices . |
| (Opcional) Se um novo documento será criado se nenhum documento corresponder ao filtro. Por padrão, este campo é configurado para |
Exemplo
Este exemplo executa as seguintes ações:
Especifica uma instância
UpdateOneModele uma instânciaUpdateManyModelem 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 |
|---|---|
| O namespace no qual a operação é executada. |
| O filtro que corresponde a um ou mais documentos que você deseja excluir. Quando especificado em um |
| (Opcional) O agrupamento a ser usado ao classificar os resultados. Para saber mais sobre agrupamentos, consulte o guia Agrupamentos. |
| (Opcional) O índice a ser usado para a operação. Para aprender mais sobre índice, consulte o guia Índices . |
Exemplo
Este exemplo executa as seguintes ações:
Especifica uma instância
DeleteOneModele uma instânciaDeleteManyModelem 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 |
|---|---|---|
| Se as operações são executadas na ordem em que foram especificadas. |
|
| Se a validação de nível de documento é ignorada. |
|
| Um comentário arbitrário para ajudar a rastrear a operação através do profiler de banco de dados, currentOp e logs. |
|
| Um mapa de nomes e valores de parâmetros a serem aplicados a todas as operações dentro da gravação em massa. Os valores devem ser expressões constantes ou fechadas que não façam referência aos campos do documento. |
|
| O write concern a ser usado para esta operação em massa. | 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.
Documentação da API
Para saber mais sobre qualquer um dos métodos ou tipos discutidos neste guia, consulte a seguinte documentação da API: