Explore o novo chatbot do Developer Center! O MongoDB AI chatbot pode ser acessado na parte superior da sua navegação para responder a todas as suas perguntas sobre o MongoDB .

Saiba por que o MongoDB foi selecionado como um líder no 2024 Gartner_Magic Quadrupnt()
Desenvolvedor do MongoDB
Central de desenvolvedor do MongoDBchevron-right
Idiomaschevron-right
Rustchevron-right

Introdução ao Rust e MongoDB

Jorge D. Ortiz-Fuentes, Mark Smith17 min read • Published Feb 10, 2022 • Updated Sep 23, 2022
Rust
Ícone do FacebookÍcone do Twitterícone do linkedin
Avalie esse Início rápido
star-empty
star-empty
star-empty
star-empty
star-empty
Emblema Rust
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.

Ferramentas e versões da série

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.

Pré-requisitos

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:
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.

Criando seu banco de dados

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:
  • Clique em "Comece grátis" na página inicial do MongoDB.
  • 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.

Iniciando seu projeto

Em seu terminal, vá para o diretório em que você mantém seus projetos de codificação e execute o seguinte comando:
1cargo 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]
2mongodb = "2.1"
3bson = { version = "2", features = ["chrono-0_4"] } # Needed for using chrono datetime in doc
4tokio = "1"
5chrono = "0.4" # Used for setting DateTimes
6serde = "1" # Used in the Map Data into Structs section
Agora você pode fazer o download e criar as dependências executando:
1cargo 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.

Configurar sua instância do MongoDB

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.

Criar um usuário

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.

Permita um endereço IP

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.

Conectando ao MongoDB

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:
1use mongodb::{Client, options::{ClientOptions, ResolverConfig}};
2use std::env;
3use std::error::Error;
4use tokio;
5
6#[tokio::main]
7async 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):
2export MONGODB_URI='mongodb+srv://yourusername:yourpasswordgoeshere@rustquickstart-123ab.mongodb.net/test?retryWrites=true&w=majority'
3
4# Windows CMD shell:
5set 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`
5Databases:
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.

BSON - Como o MongoDB entende os dados

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:
1use chrono::{TimeZone, Utc};
2use mongodb::bson::doc;
3
4let 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.

Criando documentos

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:
2let 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:
1let insert_result = movies.insert_one(new_doc.clone(), None).await?;
2println!("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:
1New 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.

Recuperar dados de uma 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:
2let movie: Document = movies
3 .find_one(
4 doc! {
5 "title": "Parasite"
6 },
7 None,
8 ).await?
9 .expect("Missing 'Parasite' document.");
10println!("Movie: {}", movie);
Este código deve resultar em uma saída como a seguinte:
1Movie: { _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!

Atualizar documentos em uma coleção

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:
2let update_result = movies.update_one(
3 doc! {
4 "_id": &movie.get("_id")
5 },
6 doc! {
7 "$set": { "year": 2019 }
8 },
9 None,
10).await?;
11println!("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:
2let movie = movies
3 .find_one(
4 doc! {
5 "_id": &movie.get("_id")
6 },
7 None,
8 ).await?
9 .expect("Missing 'Parasite' document.");
10println!("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.
1Updated 1 document
2Updated 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") }

Excluir documentos de uma coleção

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":
2let delete_result = movies.delete_many(
3 doc! {
4 "title": "Parasite"
5 },
6 None,
7).await?;
8println!("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.

Usando serde para mapear dados em estruturas

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):
1use serde::{Deserialize, Serialize};
2use mongodb::bson::{Bson, oid::ObjectId};
3
4// Working with Document can be verbose:
5if 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#[derive(Serialize, Deserialize, Debug)]
3struct Movie {
4 #[serde(rename = "_id", skip_serializing_if = "Option::is_none")]
5 id: Option<ObjectId>,
6 title: String,
7 year: i32,
8 plot: String,
9 #[serde(with = "bson::serde_helpers::chrono_datetime_as_bson_datetime")]
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:
2let 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:
9let serialized_movie = bson::to_bson(&captain_marvel)?;
10let document = serialized_movie.as_document().unwrap();
11
12// Insert into the collection and extract the inserted_id value:
13let insert_result = movies.insert_one(document.to_owned(), None).await?;
14let captain_marvel_id = insert_result
15 .inserted_id
16 .as_object_id()
17 .expect("Retrieved _id should have been of type ObjectId");
18println!("Captain Marvel document ID: {:?}", captain_marvel_id);
Quando executei o código acima, o resultado foi parecido com este:
1Captain 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:
3let 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
9let loaded_movie_struct: Movie = bson::from_bson(Bson::Document(loaded_movie))?;
10println!("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):
1Movie loaded from collection: Movie { id: Some(ObjectId(5e835f30007760020028b0ae)), title: "Captain Marvel", year: 2019 }
Você pode conferir o exemplo de código completo do Tokio no github.

Quando você não quer executar com Tokio

Async-std

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]
2async-std = "1"
3mongodb = { 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.
1use async_std;
2
3#[async_std::main]
4async fn main() -> Result<(), Box<dyn Error>> {
5 // Your code goes here.
6}
Você pode conferir o exemplo completo do código async-std no github.

Código síncrono

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]
2mongodb = { 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:
1use mongodb::sync::Client;
2
3// Use mongodb::sync::Client, instead of mongodb::Client:
4let client = Client::with_uri_str(client_uri.as_ref())?;
5
6// .insert_one().await? becomes .insert_one()?
7let insert_result = movies.insert_one(new_doc.clone(), None)?;
Você pode conferir o exemplo de código síncrono completo no github.

Leitura adicional

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.

Conclusão

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 cratebson 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.

Ícone do FacebookÍcone do Twitterícone do linkedin
Avalie esse Início rápido
star-empty
star-empty
star-empty
star-empty
star-empty
Relacionado
Artigo

Como o Prisma analisa um esquema de um banco de dados MongoDB


May 19, 2022 | 8 min read
Artigo

Usando MongoDB com Rust Web Development Framework


Aug 29, 2024 | 1 min read
exemplo de código

Projeto de programação para novatos: criar um mecanismo de blog com Rust e MongoDB


Sep 11, 2024 | 0 min read
Tutorial

Escrevendo uma API com MongoDB no Rust


Jun 10, 2024 | 10 min read
Sumário