Introdução ao Rust e MongoDB
Avalie esse Início rápido
Esta publicação de Início Rápido ajudará você a conectar seu aplicativo Rust a um cluster do MongoDB. Em seguida, mostrará como realizar operações CRUD em uma coleção. Finalmente, abordará como usar o serde para mapear entre os BSON do MongoDB e as estruturas Rust.
Esta série pressupõe que você tenha uma versão recente da cadeia de ferramentas Rust instalada (v1.57+), e que está familiarizado com a sintaxe do Rust. Também pressupõe que você esteja razoavelmente confortável com o uso da linha de comando e do seu editor de código favorito.
Rust é uma linguagem de programação de sistemas poderosa com alto desempenho e baixo uso de memória, adequada para uma grande variedade de tarefas. Embora atualmente seja uma linguagem de nicho para trabalhar com dados, sua popularidade está aumentando rapidamente.
Se você usa o Rust e deseja trabalhar com o MongoDB, esta série de blogs é o lugar certo para começar! Vou lhe mostrar como fazer o seguinte:
- Instale o driver MongoDB Rust. O driver Rust é o crate mongodb que permite se comunicar com um cluster do MongoDB.
- Conecte-se a uma instância do MongoDB.
- Crie, leia, atualize e exclua (CRUD) documentos em seu banco de dados.
As publicações posteriores da série abordarão coisas fluxos de alterações, transações e o incrível recurso pipeline de agregação, que permite executar queries avançadas em seus dados.
Vou presumir que você tenha um conhecimento funcional do Rust. Não usarei nenhum código Rust complexo – este é um tutorial do MongoDB, não do Rust – mas você deve saber pelo menos o básico sobre tratamento de erros e empréstimos no Rust! Talvez você queira executar
rustup update
se não o fez desde janeiro 2022, pois trabalharemos com uma versão recente.Você precisará do seguinte:
- Uma cadeia de ferramentas Rust atualizada, versão 1.47+. Recomendamos instalá-la com o Rustup, caso ainda não o tenha feito.
- Um editor de código de sua escolha. Eu recomendo o IntelliJ Rust ou o VS Code gratuito com o plug-in oficial do Rust
O driver MongoDB Rust usa o Tokio por padrão - e este tutorial fará isso também. Se você estiver interessado em executar em async-std ou de forma síncrona, as alterações são diretas. Vou abordá-los no final.
Você usará o MongoDB Atlas para hospedar um MongoDB cluster, portanto, não precisa se preocupar com a configuração do próprio MongoDB.
Comece com um cluster M0 no Atlas. É gratuito para sempre e é a maneira mais fácil de experimentar as etapas desta série de blogs. Você nem precisará fornecer detalhes de pagamento.
Você precisará criar um novo cluster e carregá-lo com dados de exemplo. Meu talentoso colega Maxime Beugnet criou um tutorial em vídeo para ajudar você, mas também explico as etapas abaixo:
- Insira seus detalhes cadastre-se com sua conta do Google, se tiver uma.
- Aceite os Termos de Serviço
- Crie um cluster Starter.
- Selecione o mesmo provedor de nuvem com o qual você está acostumado ou deixe-o como está. Escolha uma região que faça sentido para você.
- Você pode alterar o nome do cluster, se quiser. Chamei o meu de "Rustquickstart".
O provisionamento do cluster levará alguns minutos; portanto, enquanto espera, você pode passar para a próxima etapa.
Em seu terminal, vá para o diretório em que você mantém seus projetos de codificação e execute o seguinte comando:
1 cargo new --bin rust_quickstart
Isso criará um novo diretório chamado
rust_quickstart
, que contém um novo projeto quase vazio. No diretório, abra Cargo.toml
e altere a seção [dependencies]
para que fique assim:1 [dependencies] 2 mongodb = "2.1" 3 bson = { version = "2", features = ["chrono-0_4"] } # Needed for using chrono datetime in doc 4 tokio = "1" 5 chrono = "0.4" # Used for setting DateTimes 6 serde = "1" # Used in the Map Data into Structs section
Agora você pode fazer o download e criar as dependências executando:
1 cargo run
Você deve ver muitas dependências baixadas e compiladas. Não se preocupe, a maior parte disso só acontece na primeira vez que você executa! No final, se tudo correu bem, ele deve imprimir "Hello, World?" no console.
Seu MongoDB cluster já deve estar configurado e em funcionamento há algum tempo, portanto, você pode ir em frente e configurar seu banco de dados para as próximas etapas.
Na interface web do Atlas, você verá um botão verde na parte inferior esquerda da tela, dizendo "Get Started". Clique nele para ver uma lista de verificação de etapas para configurar seu banco de dados. Clique em cada um dos itens da lista (incluindo o item opcional "Load Sample Data") e isso ajudará você nas etapas de configuração.
Seguindo as etapas de "Introdução", crie um usuário com "Acesso de leitura e gravação a qualquer banco de dados". Você pode escolher qualquer nome de usuário e senha. Tome nota deles, por que você vai precisar deles em um minuto. Use o botão "gerar senha segura automaticamente" para garantir que você tenha uma senha longa e aleatória que também seja segura para colar em sua string de conexão posteriormente.
Ao implantar um aplicativo com dados confidenciais, você deve permitir apenas o endereço IP dos servidores que precisam se conectar ao seu banco de dados. Clique no botão "Adicionar endereço IP", clique em "Adicionar endereço IP atual" e, por fim, clique em "Confirmar". Você também pode definir um limite de tempo em uma entrada da lista de acesso para aumentar a segurança. Observe que, às vezes, seu endereço IP pode mudar, portanto, se você perder a capacidade de se conectar ao MongoDB cluster durante este tutorial, volte e repita essas etapas.
Agora você captou a essência deste tutorial: conectar seu código Rust a um MongoDB database! A última etapa da lista de verificação "Começar" é "Conecte-se ao seu cluster". Selecione "Conecte seu aplicativo".
Normalmente, na caixa de diálogo exibida, você seleciona "Rust" no menu "Driver", mas como o driver Rust acabou de ser lançado, ele pode não estar na lista! Você deve selecionar "Python" com uma versão de "3.6 ou posterior".
Certifique-se de que a Etapa 2 tenha "Somente string de conexão" destacada e pressione o botão "Copiar" para copiar o URL para sua área de trabalho (apenas armazená-lo temporariamente em um arquivo de texto é suficiente). Cole-o no mesmo local onde armazenou seu nome de usuário e senha. Observe que o URL tem
<password>
como espaço reservado para sua senha. Você deve colar sua senha aqui, substituindo todo o espaço reservado, incluindo os caracteres '<' e '>'.De volta ao seu projeto Rust, abra
main.rs
e substitua o conteúdo pelo seguinte:1 use mongodb::{Client, options::{ClientOptions, ResolverConfig}}; 2 use std::env; 3 use std::error::Error; 4 use tokio; 5 6 7 async fn main() -> Result<(), Box<dyn Error>> { 8 // Load the MongoDB connection string from an environment variable: 9 let client_uri = 10 env::var("MONGODB_URI").expect("You must set the MONGODB_URI environment var!"); 11 12 // A Client is needed to connect to MongoDB: 13 // An extra line of code to work around a DNS issue on Windows: 14 let options = 15 ClientOptions::parse_with_resolver_config(&client_uri, ResolverConfig::cloudflare()) 16 .await?; 17 let client = Client::with_options(options)?; 18 19 // Print the databases in our MongoDB cluster: 20 println!("Databases:"); 21 for name in client.list_database_names(None, None).await? { 22 println!("- {}", name); 23 } 24 25 Ok(()) 26 }
Para executar isso, você precisará definir a variável de ambiente MONGODB_URI para a string de conexão obtida acima. Execute um dos seguintes comandos em sua janela de terminal, dependendo de sua plataforma:
1 # Unix (including MacOS): 2 export MONGODB_URI='mongodb+srv://yourusername:yourpasswordgoeshere@rustquickstart-123ab.mongodb.net/test?retryWrites=true&w=majority' 3 4 # Windows CMD shell: 5 set MONGODB_URI='mongodb+srv://yourusername:yourpasswordgoeshere@rustquickstart-123ab.mongodb.net/test?retryWrites=true&w=majority' 6 7 # Powershell: 8 $Env:MONGODB_URI='mongodb+srv://yourusername:yourpasswordgoeshere@rustquickstart-123ab.mongodb.net/test?retryWrites=true&w=majority'
Depois de fazer isso, você pode
cargo run
esse código, e o resultado deverá ser semelhante a este:1 $ cargo run 2 Compiling rust_quickstart v0.0.1 (/Users/judy2k/development/rust_quickstart) 3 Finished dev [unoptimized + debuginfo] target(s) in 3.35s 4 Running `target/debug/rust_quickstart` 5 Databases: 6 - sample_airbnb 7 - sample_analytics 8 - sample_geospatial 9 - sample_mflix 10 - sample_supplies 11 - sample_training 12 - sample_weatherdata 13 - admin 14 - local
Parabéns! Você acabou de conectar seu programa Rust ao MongoDB e listar os bancos de dados em seu cluster. Se você não vir esta lista, talvez não tenha carregado os dados de amostra com êxito no cluster, e então será necessário voltar algumas etapas até que a execução desse comando mostre a lista acima.
Antes de prosseguir com a consulta e atualizar seu banco de dados, é útil ter uma visão geral do BSON e como ele se relaciona com o MongoDB. BSON é o formato de dados binários usado pelo MongoDB para armazenar todos os seus dados. O BSON também é o formato usado pela query e pelos pipelines de agregação do MongoDB (falarei sobre isso mais tarde).
É análogo ao JSON e lida com todos os mesmos tipos principais, como números, strings, arrays e objetos (que são chamados de documentos no BSON), mas o BSON é compatível com mais tipos do que o JSON. Isso inclui datas e decimais, e há um tipo especial de ObjectId geralmente usado para identificar documentos em uma coleção do MongoDB. Como o BSON é um formato binário, ele não é legível por humanos – geralmente, quando é impresso na tela, ele será impresso para se parecer com JSON.
Devido à incompatibilidade entre o esquema dinâmico do BSON e o sistema de tipos estáticos do Rust, lidar com o BSON no Rust pode ser complicado. Felizmente, o crate
bson
fornece algumas ferramentas úteis para lidar com dados BSON, incluindo a macro doc!
para gerar o documento BSON, e implementa serde para a capacidade de serializar e desserializar entre estruturas Rust e dados BSON.A criação de uma estrutura de documento usando a macro
doc!
tem a seguinte aparência:1 use chrono::{TimeZone, Utc}; 2 use mongodb::bson::doc; 3 4 let new_doc = doc! { 5 "title": "Parasite", 6 "year": 2020, 7 "plot": "A poor family, the Kims, con their way into becoming the servants of a rich family, the Parks. But their easy life gets complicated when their deception is threatened with exposure.", 8 "released": Utc.ymd(2020, 2, 7).and_hms(0, 0, 0), 9 };
Se você usar
println!
para imprimir o valor de new_doc
no console, deverá ver algo assim:1 { title: "Parasite", year: 2020, plot: "A poor family, the Kims, con their way into becoming the servants of a rich family, the Parks. But their easy life gets complicated when their deception is threatened with exposure.", released: Date("2020-02-07 00:00:00 UTC") }
(Aliás, Parasita é um filme absolutamente incrível. Ele ainda não está no banco de dados com o qual você trabalhará porque foi lançado em 2020, mas o conjunto de dados foi atualizado pela última vez em 2015.)
Embora a saída acima se pareça um pouco com JSON, essa é apenas a maneira como a biblioteca BSON implementa a característica
Display
. Os dados ainda são tratados como dados binários nos bastidores.Todos os exemplos a seguir usam o conjunto de dados sample_mflix que você carregou em seu cluster do Atlas. Ele contém uma coleção divertida chamada
movies
, com detalhes de uma série de filmes com lançamentos que datam de 1903, do banco de dados do IMDB.O tipo cliente permite obter a lista de bancos de dados em seu cluster, mas não muito mais que isso. Para começar a trabalhar com dados, você precisará obter um banco de dados usando os métodos
database
ou database_with_options
do cliente. Você fará isso na próxima seção.O código na última seção constrói um documento na memória e agora você irá persisti-lo no banco de dados de filmes. A primeira etapa antes de fazer qualquer coisa com uma coleção do MongoDB é obter um objeto coleção do seu banco de dados. Isso é feito da seguinte forma:
1 // Get the 'movies' collection from the 'sample_mflix' database: 2 let movies = client.database("sample_mflix").collection("movies");
Se você navegou na coleção de filmes com o Compass ou a aba "Coleções" no Atlas, verá que a maioria dos registros tem mais campos do que o documento que criei acima usando a macro
doc!
. Como o MongoDB não impõe um esquema dentro de uma coleção por padrão, isso está adequado, e apenas reduzi o número de campos para legibilidade. Depois de ter uma referência à sua coleção do MongoDB, você pode usar o método insert_one
para inserir um único documento:1 let insert_result = movies.insert_one(new_doc.clone(), None).await?; 2 println!("New document ID: {}", insert_result.inserted_id);
O método
insert_one
retorna o tipo Result<InsertOneResult>
que pode ser usado para identificar qualquer problema ao inserir o documento, e pode ser usado para encontrar o ID gerado para o novo documento no MongoDB. Se você adicionar este código à sua função principal, ao executá-la, deverá ver algo como o seguinte:1 New document ID: ObjectId("5e835f3000415b720028b0ad")
Este código insere um único
Document
em uma coleção. Se você quiser inserir vários documentos em massa, é mais eficiente usar insert_many
, que usa um IntoIterator
de documentos que serão inseridos na coleção.Como sei que não há outros documentos na coleção com o nome Parasite, você pode procurá-lo pelo título usando o código a seguir, em vez do ID recuperado quando você inseriu o registro:
1 // Look up one document: 2 let movie: Document = movies 3 .find_one( 4 doc! { 5 "title": "Parasite" 6 }, 7 None, 8 ).await? 9 .expect("Missing 'Parasite' document."); 10 println!("Movie: {}", movie);
Este código deve resultar em uma saída como a seguinte:
1 Movie: { _id: ObjectId("5e835f3000415b720028b0ad"), title: "Parasite", year: 2020, plot: "A poor family, the Kims, con their way into becoming the servants of a rich family, the Parks. But their easy life gets complicated when their deception is threatened with exposure.", released: Date("2020-02-07 00:00:00 UTC") }
É muito semelhante à saída acima, mas quando você inseriu o registro, o driver do MongoDB gerou um ObjectId exclusivo para você identificar esse documento. Cada documento em uma coleção do MongoDB tem um valor
_id
exclusivo. Você mesmo pode fornecer um valor se tiver um que seja garantidamente exclusivo, ou o MongoDB gerará um para você, como fez nesse caso. Normalmente, é uma boa prática definir explicitamente um valor para você.O método find_one é útil para recuperar um único documento de uma coleção, mas geralmente você precisará pesquisar vários registros. Nesse caso, você precisará do método find, que usa opções semelhantes a essa chamada, mas retorna um
Result<Cursor>
. O Cursor
é usado para iterar pela lista de dados retornados.As operações de localização, juntamente com os documentos de filtro correspondentes, são muito poderosas, e você provavelmente as usará muito. Se você precisar de mais flexibilidade do que
find
e find_one
podem fornecer, recomendamos verificar a documentação sobre pipelines de agregação, que são superpotentes e, na minha opinião, um dos recursos mais poderosos do MongoDB. Escreverei outra publicação no blog nesta série apenas sobre esse tópico. Mal posso esperar!Após ser armazenado em uma coleção, um documento pode ser atualizado de várias maneiras. Se quiser substituir completamente um documento por outro, você pode usar o método find_one_and_replace, mas é mais comum atualizar uma ou mais partes de um documento, usando update_one ou update_many. Cada atualização de documento separada é atômica, o que pode ser um recurso útil para manter seus dados consistentes em um documento. No entanto, tenha em mente que
update_many
não é uma operação atômica. Para isso, você precisará usar transações ACID multidocumento, disponíveis no MongoDB desde a versão 4.0 (e disponíveis para coleções fragmentadas desde 4.2). A versão 2.x do driver Rust permite transações para conjuntos de réplicas.Para atualizar um único documento no MongoDB, você precisa de dois documentos BSON: o primeiro descreve a query para localizar o documento do MongoDB que você deseja atualizar; o segundo documento descreve as operações de atualização que você gostaria de realizar no documento da coleção. Embora a data de "lançamento" de Parasita fosse em 2020, acho que isso se refere ao lançamento nos EUA. O ano correto de lançamento foi 2019, então aqui está o código para atualizar o registro:
1 // Update the document: 2 let update_result = movies.update_one( 3 doc! { 4 "_id": &movie.get("_id") 5 }, 6 doc! { 7 "$set": { "year": 2019 } 8 }, 9 None, 10 ).await?; 11 println!("Updated {} document", update_result.modified_count);
Quando você executa o comando acima, ele deve imprimir "1 documento atualizado". Caso contrário, algo aconteceu com o documento de filme inserido anteriormente. Talvez você o tenha excluído? Apenas para verificar se a atualização atualizou o valor do ano corretamente, aqui está um comando
find_one
que você pode adicionar ao seu programa para ver como é o documento atualizado:1 // Look up the document again to confirm it's been updated: 2 let movie = movies 3 .find_one( 4 doc! { 5 "_id": &movie.get("_id") 6 }, 7 None, 8 ).await? 9 .expect("Missing 'Parasite' document."); 10 println!("Updated Movie: {}", &movie);
Quando executei esses blocos de código, o resultado ficou parecido com o texto abaixo. Veja como isso mostra que o ano agora é 2019 em vez de 2020.
1 Updated 1 document 2 Updated Movie: { _id: ObjectId("5e835f3000415b720028b0ad"), title: "Parasite", year: 2019, plot: "A poor family, the Kims, con their way into becoming the servants of a rich family, the Parks. But their easy life gets complicated when their deception is threatened with exposure.", released: Date("2020-02-07 00:00:00 UTC") }
Nas seções acima você aprendeu como criar, ler e atualizar documentos na coleção. Se você executou seu programa algumas vezes, provavelmente criou alguns documentos para o filme Parasita! Agora é um bom momento para limpar isso usando o método
delete_many
. O driver Rust do MongoDB fornece 3 métodos para excluir documentos:find_one_and_delete
excluirá um único documento de uma coleção e retornará o documento que foi excluído, se ele existir.delete_one
encontrará os documentos que correspondem a um filtro fornecido e excluirá o primeiro encontrado (se houver).delete_many
, como você pode esperar, encontrará os documentos correspondentes a um filtro fornecido e excluirá todos eles.
No código abaixo, usei
delete_many
porque você pode ter criado vários registros ao testar o código acima. O filtro apenas procura o filme por nome, que corresponderá e excluirá todos os documentos inseridos, enquanto se você pesquisar por um valor_id
, ele excluirá apenas um, porque os IDs são exclusivos.Se você estiver constantemente filtrando ou classificando um campo, considere adicionar um índice a esse campo para melhorar o desempenho à medida que sua collection cresce. Confira o Manual do MongoDB para obter mais detalhes.
1 // Delete all documents for movies called "Parasite": 2 let delete_result = movies.delete_many( 3 doc! { 4 "title": "Parasite" 5 }, 6 None, 7 ).await?; 8 println!("Deleted {} documents", delete_result.deleted_count);
Você conseguiu! Criar, ler, atualizar e excluir operações são as operações principais que você usará novamente para acessar e gerenciar os dados em seu cluster do MongoDB. Depois da amostra que este tutorial fornece, sem dúvida vale a pena ler com mais detalhes o seguinte:
- Consultar documentos que são usados para todas as operações de leitura, atualização e exclusão.
- A crate e a documentação do MongoDB que descrevem todas as operações que o driver do MongoDB fornece para acessar e modificar seus dados.
- O crate BSON e os docs que o acompanham descrevem como criar e mapear dados para inserção ou recuperação do MongoDB.
- O crate serde fornece o framework para o mapeamento entre tipos de dados Rust e BSON com o crate bson, portanto, é importante aprender como aproveitá-lo.
Um dos recursos do crate BSON que pode não ser imediatamente aparente é que ele fornece um formato de dados BSON para a estrutura
serde
. Isso significa que você pode aproveitar o crate Serde para mapear entre os tipos de dados Rust e os BSON types para persistência no MongoDB.Para ver como isso é útil, consulte o seguinte exemplo de como acessar o campo
title
do documento new_movie
(sem serde):1 use serde::{Deserialize, Serialize}; 2 use mongodb::bson::{Bson, oid::ObjectId}; 3 4 // Working with Document can be verbose: 5 if let Ok(title) = new_doc.get_str("title") { 6 println!("title: {}", title); 7 } else { 8 println!("no title found"); 9 }
A primeira linha do código acima recupera o valor de
title
e, em seguida, tenta recuperá-lo como uma string (Bson::as_str
retorna None
se o valor for de um tipo diferente). Há muito tratamento de erros e conversão envolvidos. O framework serde oferece a capacidade de definir uma estrutura como a abaixo, com campos que correspondem ao documento que você espera receber.1 // You use `serde` to create structs which can serialize & deserialize between BSON: 2 3 struct Movie { 4 5 id: Option<ObjectId>, 6 title: String, 7 year: i32, 8 plot: String, 9 10 released: chrono::DateTime<Utc>, 11 }
Observe o uso das macros
Serialize
e Deserialize
que informam ao serde que essa estrutura pode ser serializada e desserializada. O atributo serde
também é usado para informar ao serde que o campo de estrutura id
deve ser serializado para BSON como _id
, que é como o MongoDB espera que seja chamado. O parâmetro skip_serializing_if = "Option::is_none"
também informa ao serde que, se o valor opcional de id
for None
, ele não deverá ser serializado. (Se você fornecer _id: None
BSON ao MongoDB, ele armazenará o documento com um id de NULL
, enquanto que se você não fornecer um, um id será gerado para você, que geralmente é o comportamento desejado.) Além disso, precisamos usar um atributo para apontar serde
para o auxiliar que ele precisa serializar e desserializar carimbos de data/hora conforme definido por chrono
.O código abaixo cria uma instância da estrutura
Movie
para o filme Capitã Marvel. (Não foi um ótimo filme? Adorei esse filme!) Depois de criar a estrutura, antes de salvá-la em sua coleção, ela precisa ser convertida em um documento BSON. Isso é feito em duas etapas: primeiro é convertido em um valor Bson com bson::to_bson
, que retorna uma instância Bson
; então ele é convertido especificamente em Document
chamando as_document
nele. É seguro chamar unwrap
neste resultado porque já sei que serializar uma estrutura para BSON cria um tipo de documento BSON.Depois que o seu programa tiver obtido uma instância bson
Document
, você poderá chamar insert_one
com ela exatamente da mesma forma que fez na seção acima chamada Criação de documentos.1 // Initialize struct to be inserted: 2 let captain_marvel = Movie { 3 id: None, 4 title: "Captain Marvel".to_owned(), 5 year: 2019, 6 }; 7 8 // Convert `captain_marvel` to a Bson instance: 9 let serialized_movie = bson::to_bson(&captain_marvel)?; 10 let document = serialized_movie.as_document().unwrap(); 11 12 // Insert into the collection and extract the inserted_id value: 13 let insert_result = movies.insert_one(document.to_owned(), None).await?; 14 let captain_marvel_id = insert_result 15 .inserted_id 16 .as_object_id() 17 .expect("Retrieved _id should have been of type ObjectId"); 18 println!("Captain Marvel document ID: {:?}", captain_marvel_id);
Quando executei o código acima, o resultado foi parecido com este:
1 Captain Marvel document ID: ObjectId(5e835f30007760020028b0ae)
É ótimo poder criar dados usando os tipos de dados nativos do Rust, mas acho que é ainda mais valioso poder desserializar dados em estruturas. Isso é o que vou mostrar a seguir. Em muitos aspectos, é o mesmo processo acima, mas ao contrário.
O código abaixo recupera um único documento de filme, converte-o em um valor
Bson::Document
e, em seguida, chama from_bson
nele, o que desserializa-o do BSON para qualquer tipo que esteja no lado esquerdo da expressão. É por isso que eu tive que especificar que loaded_movie
é do tipo Movie
no lado esquerdo, em vez de apenas permitir que o compilador rust derive essa informação para mim. Uma alternativa é usar a notação turbofish na na chamada from_bson
, chamando explicitamente from_bson::<Movie>(loaded_movie)
. No final das contas, como em muitas questões do Rust, a escolha é sua.1 // Retrieve Captain Marvel from the database, into a Movie struct: 2 // Read the document from the movies collection: 3 let loaded_movie = movies 4 .find_one(Some(doc! { "_id": captain_marvel_id.clone() }), None) 5 .await? 6 .expect("Document not found"); 7 8 // Deserialize the document into a Movie instance 9 let loaded_movie_struct: Movie = bson::from_bson(Bson::Document(loaded_movie))?; 10 println!("Movie loaded from collection: {:?}", loaded_movie_struct);
E, finalmente, aqui está o que obtive quando imprimi a representação de depuração da estrutura Movie (é por isso que derivei
Debug
na definição da estrutura acima):1 Movie loaded from collection: Movie { id: Some(ObjectId(5e835f30007760020028b0ae)), title: "Captain Marvel", year: 2019 }
Se você preferir usar
async-std
em vez de tokio
, está com sorte! As mudanças são triviais. Primeiro, você precisa desabilitar os recursos padrão e habilitar o recurso async-std-runtime
:1 [dependencies] 2 async-std = "1" 3 mongodb = { version = "2.1", default-features = false, features = ["async-std-runtime"] }
As únicas alterações que você precisará fazer em seu código rust é adicionar
use async_std;
às importações e marcar sua função principal assíncrona com #[async_std::main]
. Todo o restante de seu código deve ser idêntico ao exemplo do Tokio.1 use async_std; 2 3 4 async fn main() -> Result<(), Box<dyn Error>> { 5 // Your code goes here. 6 }
Se não quiser executar em um framework assíncrono, você pode habilitar o recurso de sincronização. Em seu arquivo
Cargo.toml
, desabilite os recursos padrão e habilite sync
:1 [dependencies] 2 mongodb = { version = "2.1", default-features = false, features = ["sync"] }
Você não precisará mais que sua função de encerramento seja um
async fn
. Você precisará usar uma interface Client
diferente, definida em mongodb::sync
, e não precisará aguardar o resultado de nenhuma das funções IO:1 use mongodb::sync::Client; 2 3 // Use mongodb::sync::Client, instead of mongodb::Client: 4 let client = Client::with_uri_str(client_uri.as_ref())?; 5 6 // .insert_one().await? becomes .insert_one()? 7 let insert_result = movies.insert_one(new_doc.clone(), None)?;
A documentação do MongoDB Rust Driver é muito boa. Como a crate BSON também é bastante aproveitada, vale a pena ter os docs também. Usei-os muito para escrever este início rápido.
Ufa! Esse foi um tutorial bem grande, não foi? As operações descritas aqui serão usadas repetidamente, portanto, é bom que você se familiarize com elas.
O que eu aprendi escrevendo o código para este tutorial é o valor que o crate
bson
fornece a você e ao driver MongoDB. Vale a pena saber pelo menos tão bem quanto o cratemongodb
, pois você o usará muito para geração e conversão de dados e é uma biblioteca enganosamente rica.Haverá mais postagens de início rápido do Rust no MongoDB Developer Hub, abordando diferentes partes do MongoDB e do MongoDB Rust Driver, então continue voltando aqui para conferir!
Se tiver dúvidas, acesse o site da nossa comunidade de desenvolvedores, no qual os engenheiros e a comunidade do MongoDB ajudarão você a desenvolver sua próxima grande ideia com o MongoDB.