Visão geral
Este guia demonstra como construir um aplicação da web usando Atix Web e MongoDB. O Atix é uma estrutura web assíncrona poderosa 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 Atix Web fornece o servidor HTTP, o roteamento e os endpoints de API para conectar seu frontend ao banco de dados MongoDB .
Camada de gerenciamento de dados: o sistema de tipos do Rust e o async/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 aplicação que:
Conecta a um cluster MongoDB Atlas que contém o conjunto de dados
sample_restaurantsExpõe um endpoint
/restaurantsque lista todos os restaurantesExpõe um endpoint
/browseque lista restaurantes no Queins com"Moon"no nomeApresenta 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 aplicação da Web Atix que se integra ao MongoDB. O aplicação 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 Atix Web, consulte o guiade Início Rápido do Driver Rust.
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 um local seguro. 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 MongoDB , definir seu modelo de dados e implementar os serviços de query do banco de dados .
Configurar 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 motorista para facilitar a observabilidade.
Cria um cliente e retorna um identificador 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 endpoints
/restaurantse/browse.Chama os serviços de consulta 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 endpoint
/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 aplicação, 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 aplicação 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 aplicação da web Atix que se conecta à implementaçã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

