Visão geral
Este guia demonstra como criar um aplicativo da web usando Atix Web e MongoDB. O Actix é um framework web assíncrono poderoso para Rust que facilita a criação de serviços HTTP rápidos e com segurança de tipo.
O aplicativo neste tutorial consiste nas seguintes camadas:
Camada de Banco de Dados: MongoDB (hospedado no MongoDB Atlas) armazena e recupera dados.
Camada do servidor: o Actix Web fornece o servidor HTTP, o roteamento e os pontos de extremidade de API para conectar seu frontend ao banco de dados MongoDB.
Camada de gerenciamento de dados: o sistema de tipos do Rust e o assíncrono/await fornecem manuseio seguro de dados com garantias de tempo de compilação.
Camada de apresentação: As páginas HTML renderizadas pelo servidor, estilizadas com CSS do Tailwind, exibem os dados de restaurante de exemplo em uma tabela.
Você construirá um pequeno aplicativo que:
Conecta a um cluster MongoDB Atlas que contém o conjunto de dados
sample_restaurantsExpõe um
/restaurantsponto de extremidade que lista todos os restaurantesExpõe um
/browseponto de extremidade que lista restaurantes no Queins com"Moon"no nomeRenderiza os resultados como uma tabela HTML com uma barra de navegação compartilhada
Por que usar o MongoDB em um aplicativo Atix?
O modelo de documento flexível do MongoDB armazena dados como documentos semelhantes a BSON/JSON. Isso funciona naturalmente com estruturas Rust que modelam seus dados, sem camadas complexas de ORM ou migrações de esquema.
Quando você combina o Atix Web e o driver assíncrono MongoDB Rust, essa pilha fornece:
Estruturas de dados flexíveis que podem desenvolver sem migrações dispendiosas
E/S assíncrona e não bloqueante para APIs de alta simultaneidade e desempenho
Forte segurança de tipo da camada do banco de dados através de seus manipuladores e modelos
Integração simples com visualizações da web (modelos HTML ou construção manual de strings, como neste tutorial)
Essa combinação funciona para aplicativos que precisam do seguinte:
Evolução de esquemas ao longo do tempo
Alta taxa de transferência e simultaneidade
Fortes garantias de tempo de compilação sobre formas de dados
Tutorial de início rápido
Este tutorial ajuda você a criar um aplicativo da Web Atix que se integra ao MongoDB. O aplicativo acessa dados de restaurante de amostra em um cluster MongoDB Atlas e exibe os resultados em seu navegador.
Dica
Se você preferir se conectar ao MongoDB usando o driver Rust sem o Actix Web, consulte o Início Rápido do Driver Rust guia.
Configurar seu projeto
Siga as etapas nesta seção para instalar pré-requisitos, criar um cluster MongoDB Atlas e organizar o projeto Rust.
Verifique os pré-requisitos
Para criar o aplicação Quick Start, verifique se você tem o seguinte instalado:
Pré-requisitos | Notas |
|---|---|
Rust | Instale a versão estável mais recente do Rust. |
Editor de código | Este tutorial usa Visual Studio Code com a extensão Rust, mas você pode usar o editor de sua escolha. |
Terminal | Use o Terminal ou aplicativo semelhante para MacOS. Use o PowerShell para Windows. |
Criar um cluster MongoDB Atlas
O MongoDB Atlas é um serviço de banco de dados de nuvem totalmente gerenciado que hospeda suas implementações do MongoDB . Se você não tiver uma implementação do MongoDB , crie um cluster do MongoDB gratuitamente (nenhum cartão de crédito necessário) concluindo o tutorial de Introdução ao MongoDB . O tutorial de Introdução ao MongoDB também demonstra como carregar conjuntos de dados de exemplo em seu cluster, incluindo o sample_restaurants banco de dados que este tutorial usa.
Importante
Certifique-se de ter o conjunto de dados sample_restaurants carregado em seu cluster antes de continuar. Um conjunto de dados sample_restaurants ausente resulta em listas de restaurantes vazias em suas páginas de amostra.
Para se conectar ao cluster MongoDB, use um URI de conexão. Para saber como recuperar seu URI de conexão, consulte a seção Adicionar sua string de conexão do tutorial de Introdução ao MongoDB.
Dica
Salve seu URI de conexão em uma localização segura. Você o adicionará a um arquivo .env mais tarde.
Configurar suas dependências de projeto
Abra Cargo.toml e substitua a seção [dependencies] pelo seguinte:
[package] name = "actix_quickstart" version = "0.1.0" edition = "2024" [dependencies] actix-web = "4" actix-files = "0.6" actix-cors = "0.7" mongodb = "3.4.1" tokio = { version = "1", features = ["rt-multi-thread", "macros"] } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" dotenv = "0.15" futures = "0.3"
Instale as novas dependências executando o seguinte comando em seu terminal:
cargo build
Essas dependências fornecem:
actix-web: servidor HTTP, roteamento e tipos de solicitação/resposta.mongodb: Driver assíncrono oficial do MongoDB para Rust.tokio: Tempo de execução assíncrono usado pelo Atix Web e pelo driver MongoDB .serde/serde_json: serialização e desserialização para dados JSON e BSON.dotenv: carrega variáveis de ambiente de um arquivo .env para desenvolvimento local.futures: Utilidades para trabalhar com fluxos assíncronos (usados para cursores MongoDB ).
Configurar o back-end
Depois de configurar o projeto, siga as etapas desta seção para configurar variáveis de ambiente, configurar sua conexão do MongoDB , definir seu modelo de dados e implementar os serviços de query do banco de dados .
Configure suas variáveis de ambiente
Crie um arquivo .env na raiz do seu projeto para armazenar seu URI de conexão MongoDB.
Execute o seguinte comando na raiz do seu projeto :
touch .env
Abra o .env e adicione seu URI de conexão e número da porta:
MONGO_URI="<your-mongodb-connection-uri>" PORT=5050
Substitua <your-mongodb-connection-uri> pelo URI de conexão que você salvou anteriormente.
Criar o módulo de conexão do banco de dados
Crie um novo arquivo denominado db.rs no diretório src para gerenciar a conexão MongoDB .
Execute o seguinte comando na raiz do seu projeto :
touch src/db.rs
Abra o db.rs e adicione o seguinte código para configurar o cliente MongoDB e a conexão do banco de dados :
use mongodb::{options::ClientOptions, Client, Database}; pub async fn init_db(mongo_uri: &str) -> Database { let mut client_options = ClientOptions::parse(mongo_uri) .await .expect("Failed to parse MongoDB connection string"); client_options.app_name = Some("actix_quickstart".to_string()); let client = Client::with_options(client_options) .expect("Failed to initialize MongoDB client"); client.database("sample_restaurants") }
Este módulo:
Analisa a string de conexão do MongoDB do seu ambiente.
Configura o app_name do driver para facilitar a observabilidade.
Cria um cliente e retorna um lidar de banco de dados para o banco de dados
sample_restaurants.
Definir o modelo de dados do restaurante
Crie um novo arquivo denominado models.rs no diretório src para definir o modelo de dados do restaurante.
Execute o seguinte comando na raiz do seu projeto :
touch src/models.rs
Abra o models.rs e adicione o seguinte código para definir a estrutura do Restaurante:
use mongodb::bson::oid::ObjectId; use serde::{Deserialize, Serialize}; pub struct RestaurantRow{ pub name: Option<String>, pub borough: Option<String>, pub cuisine: Option<String>, pub id: Option<ObjectId>, }
Esta estrutura representa um documento de restaurante na coleção MongoDB . Ele usa anotações Serde para mapear campos BSON para campos de estrutura Rust.
Criar o serviço de query do restaurante
Crie um módulo de serviço que isole a lógica de query do MongoDB dos manipuladores HTTP.
Execute os seguintes comandos na raiz do seu projeto :
mkdir -p src/services touch src/services/restaurant_queries.rs
Abra o restaurant_queries.rs e adicione o seguinte código:
use futures::stream::TryStreamExt; use mongodb::{ bson::doc, Collection, }; use crate::models::RestaurantRow; pub async fn fetch_all(restaurants: &Collection<RestaurantRow>) -> Result<Vec<RestaurantRow>, mongodb::error::Error> { let cursor = restaurants .find(doc! {}) .projection(doc! { "name": 1, "borough": 1, "cuisine": 1, "_id": 1, }) .await?; cursor.try_collect().await } pub async fn fetch_by_borough( restaurants: &Collection<RestaurantRow>, borough: &str, name: &str, ) -> Result<Vec<RestaurantRow>, mongodb::error::Error> { let filter = doc! { "borough": borough, "name": { "$regex": name, "$options": "i" } }; let cursor = restaurants .find(filter) .projection(doc! { "name": 1, "borough": 1, "cuisine": 1, "_id": 1, }) .await?; cursor.try_collect().await }
Este arquivo contém duas funções assíncronas:
fetch_all(): Retorna todos os restaurantes com uma projeção de campo .fetch_by_borough(): retorna restaurantes filtrados por bairro e por um regex de nome que não diferencia maiúsculas de minúsculas.
Ambas as funções retornam Vec<RestaurantRow> para que sua camada de apresentação não precise lidar com BSON bruto.
Configurar o front-end
Agora que as camadas de banco de dados e serviço estão em vigor, configure o Atix Web para:
Inicializar a conexão do MongoDB
Definir estado compartilhado do aplicação
Exponha os endpoints
/restaurantse/browseRenderizar páginas HTML com Tailwind CSS
Criar os manipuladores de rota HTTP
Crie um módulo que contenha seus manipuladores de rota HTTP do Atix Web e lógica de renderização HTML.
Na raiz do seu projeto , execute o seguinte comando:
touch src/pages.rs
Abra o pages.rs e adicione o seguinte código:
use actix_web::{get, web, HttpResponse, Responder}; use crate::{ AppState, models::RestaurantRow, services::restaurant_queries, }; // Test endpoint to fetch all restaurants async fn get_restaurants(data: web::Data<AppState>) -> impl Responder { let result = restaurant_queries::fetch_all(&data.restaurants).await; match result { Ok(rows) => { let html = render_table_page("All Restaurants", &rows); HttpResponse::Ok() .content_type("text/html; charset=utf-8") .body(html) } Err(e) => HttpResponse::InternalServerError().body(format!("DB error: {e}")), } } // Endpoint to fetch restaurants by borough. Queens is used as an example. async fn get_restaurants_by_borough(data: web::Data<AppState>) -> impl Responder { let borough = "Queens"; // For demonstration, we use a fixed borough. This could be made dynamic. let name = "Moon"; // For demonstration, we use a fixed name filter. This could be made dynamic. let result = restaurant_queries::fetch_by_borough(&data.restaurants, borough, name).await; match result { Ok(rows) => { let title = format!(r#"{} Restaurants with "{}" in the Name"#, borough, name); let html = render_table_page(&title, &rows); HttpResponse::Ok() .content_type("text/html; charset=utf-8") .body(html) } Err(e) => HttpResponse::InternalServerError().body(format!("DB error: {e}")), } } // HTML Renderer fn render_table_page(title: &str, rows: &[RestaurantRow]) -> String { let mut html = String::new(); html.push_str(r#" <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <script src="https://cdn.tailwindcss.com"></script> <title>"#); html.push_str(title); html.push_str(r#"</title> </head> <body class="w-full"> "#); // Navigation Bar html.push_str(r#" <nav class="bg-white px-6 py-2 shadow-md w-full"> <div class="flex justify-between items-center"> <a href="/restaurants"> <img alt="MongoDB Logo" class="h-10 inline" src="https://d3cy9zhslanhfa.cloudfront.net/media/3800C044-6298-4575-A05D5C6B7623EE37/4B45D0EC-3482-4759-82DA37D8EA07D229/webimage-8A27671A-8A53-45DC-89D7BF8537F15A0D.png" /> </a> <a href="/browse" class="text-lime-800 text-lg font-semibold hover:text-lime-700"> Browse </a> </div> </nav> "#); // Page Title html.push_str(r#"<h2 class="text-lg font-semibold px-6 py-4">"#); html.push_str(title); html.push_str("</h2>"); // Table Wrapper html.push_str( r#"<div class="border border-gray-200 shadow-md rounded-lg overflow-hidden mx-6 mb-6"> <div class="relative w-full overflow-auto"> <table class="w-full caption-bottom text-sm"> <thead class="[&_tr]:border-b bg-gray-50"> <tr class="border-b transition-colors hover:bg-muted/50"> <th class="px-4 py-3 text-left text-sm font-bold text-gray-700 w-1/3"> Name </th> <th class="px-4 py-3 text-left text-sm font-bold text-gray-700 w-1/3"> Borough </th> <th class="px-4 py-3 text-left text-sm font-bold text-gray-700 w-1/3"> Cuisine </th> </tr> </thead> <tbody class="[&_tr:last_child]:border-0"> "#, ); // Table Rows for row in rows { html.push_str(r#"<tr class="border-b transition-colors hover:bg-gray-50">"#); html.push_str(r#"<td class="p-4 align-middle">"#); html.push_str(row.name.as_deref().unwrap_or("")); html.push_str("</td>"); html.push_str(r#"<td class="p-4 align-middle">"#); html.push_str(row.borough.as_deref().unwrap_or("")); html.push_str("</td>"); html.push_str(r#"<td class="p-4 align-middle">"#); html.push_str(row.cuisine.as_deref().unwrap_or("")); html.push_str("</td>"); html.push_str("</tr>"); } // Closing tags html.push_str(r#" </tbody> </table> </div> </div> "#); html.push_str("</body></html>"); html }
Este módulo:
Define os pontos de extremidade
/restaurantse/browse.Chama os serviços de query do banco de dados
fetch_allefetch_by_borough.Renderiza uma página HTML completa com CSS Tailwind e uma barra de navegação reutilizável.
Atualizar o arquivo principal do aplicativo
Substitua o conteúdo de main.rs pelo seguinte código:
mod db; mod models; mod services; mod pages; use actix_web::{get, web, App, HttpResponse, HttpServer, Responder}; use dotenv::dotenv; use mongodb::bson::doc; use mongodb::Collection; use std::env; use crate::models::RestaurantRow; // Shared state to hold the MongoDB collection #[derive(Clone)] struct AppState { restaurants: Collection<RestaurantRow>, } #[get("/health")] async fn health_check() -> impl Responder { HttpResponse::Ok().body("Healthy") } #[actix_web::main] async fn main() -> std::io::Result<()> { dotenv().ok(); let mongo_uri = env::var("MONGO_URI").expect("MONGO_URI must be set in .env file"); let port: u16 = env::var("PORT") .unwrap_or_else(|_| "5050".to_string()) .parse() .expect("PORT must be a valid u16 number"); print!("Starting server on port {port}...\n"); let db = db::init_db(&mongo_uri).await; let restaurants: Collection<RestaurantRow> = db.collection::<RestaurantRow>("restaurants"); // Extra ping to be sure connection is working let ping_result = db.run_command(doc! {"ping": 1},).await; print!("MongoDB ping result: {ping_result:?}\n"); let state = AppState {restaurants}; HttpServer::new(move || { App::new() .app_data(web::Data::new(state.clone())) .service(health_check) .service(pages::get_restaurants) .service(pages::get_restaurants_by_borough) }) .bind(("127.0.0.1", port))? .run() .await }
Este arquivo:
Declara os módulos utilizados no aplicativo (
db,models,services,pages).Define uma estrutura
AppStateque contém a coleção de restaurantes, compartilhada entre os manipuladores.Implementa o ponto de extremidade
/health.Lê
MONGO_URIePORTdo ambiente.Inicializa o banco de dados MongoDB e a coleção
restaurants.Faz o ping no cluster do MongoDB para verificar a conectividade.
Inicia um servidor HTTP Atix Web e registra suas rotas:
/health/restaurants/browse
Verifique a estrutura do seu arquivo
Antes de executar o aplicativo, verifique se a árvore de arquivos está estruturada de forma semelhante a esta:
actix-quickstart ├── Cargo.toml <-- Project config + dependencies> ├── .env <-- Environment variables> └── src ├── main.rs <-- Application entry point> ├── db.rs <-- MongoDB connection module> ├── models.rs <-- RestaurantRow model + BSON mapping> ├── pages.rs <-- HTTP route handlers + HTML rendering> └── services ├── mod.rs <-- Service module exports> └── restaurant_queries.rs <-- MongoDB query services>
As ferramentas Rust criam arquivos adicionais, como target/, quando você constrói. Você pode ignorar esses arquivos com segurança.
Execute seu aplicativo
Siga as etapas restantes para iniciar o servidor e visualizar os dados do restaurante renderizados.
Inicie o servidor da Web Atix
Na raiz do seu projeto , execute o seguinte comando para iniciar o servidor:
cargo run
O Cargo compila seu aplicativo e inicia o servidor da Web do Atix na porta 5050 definida no seu arquivo .env.
Quando bem-sucedido, você verá um resultado semelhante a este:
Starting server on port 5050... MongoDB ping result: Ok(Document({"ok": Int32(1)}))
Parabéns por concluir o tutorial de início rápido!
Depois de concluir estas etapas, você tem um aplicativo da web Atix que se conecta à implantação do MongoDB, executa queries em dados de restaurantes de amostra e renderiza os resultados.
Recursos adicionais
Para saber mais sobre Atix Web, MongoDB e ferramentas relacionadas, consulte:
Documentação daWeb do Atix

