Menu Docs
Página inicial do Docs
/ /

Integre o MongoDB com o Atix

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_restaurants

  • Expõe um endpoint /restaurants que lista todos os restaurantes

  • Expõe um endpoint /browse que lista restaurantes no Queins com "Moon" no nome

  • Apresenta os resultados como uma tabela HTML com uma barra de navegação compartilhada

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

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.

Siga as etapas nesta seção para instalar pré-requisitos, criar um cluster MongoDB Atlas e organizar o projeto Rust.

1

Para criar o aplicação Quick Start, verifique se você tem o seguinte instalado:

Pré-requisitos
Notas

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.

2

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.

3

Execute o seguinte comando no seu terminal para criar um novo projeto Rust :

cargo new actix-quickstart
cd actix-quickstart

Este comando cria um novo projeto Rust denominado actix-quickstart e navega até o diretório do projeto .

4

Abra Cargo.toml e substitua a seção [dependencies] pelo seguinte:

atix-quickstart/Cargo.toml
[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 ).

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 .

1

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.

2

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 :

atix-quickstart/src/db.rs
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 .

3

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:

atix-quickstart/src/models.rs
use mongodb::bson::oid::ObjectId;
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize)]
pub struct RestaurantRow{
pub name: Option<String>,
pub borough: Option<String>,
pub cuisine: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
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.

4

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:

actix-quickstart/src/services/restaurant_queries.rs
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.

5

Execute o seguinte comando na raiz do seu projeto :

touch src/services/mod.rs

Abra o mod.rs e adicione o seguinte código para exportar o módulo restaurant_queries:

atix-quickstart/src/services/mod.rs
pub mod restaurant_queries;

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 /restaurants e /browse

  • Renderizar páginas HTML com Tailwind CSS

1

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:

atix-quickstart/src/pages.rs
use actix_web::{get, web, HttpResponse, Responder};
use crate::{
AppState,
models::RestaurantRow,
services::restaurant_queries,
};
// Test endpoint to fetch all restaurants
#[get("/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.
#[get("/browse")]
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 /restaurants e /browse.

  • Chama os serviços de consulta do banco de dados fetch_all e fetch_by_borough.

  • Renderiza uma página HTML completa com CSS Tailwind e uma barra de navegação reutilizável.

2

Substitua o conteúdo de main.rs pelo seguinte código:

atix-quickstart/src/main.rs
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 AppState que contém a coleção de restaurantes, compartilhada entre os manipuladores.

  • Implementa o endpoint /health .

  • MONGO_URI e PORT do 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

3

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.

Siga as etapas restantes para iniciar o servidor e visualizar os dados do restaurante renderizados.

1

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)}))
2

Abra seu navegador da web e navegue até http://localhost:5050/restaurants para ver todos os restaurantes.

Página de restaurantes
3

Clique no link Browse no cabeçalho para ver uma lista filtrada de restaurantes no Queins com Moon no nome.

Navegar na página de restaurantes

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.

Para saber mais sobre Atix Web, MongoDB e ferramentas relacionadas, consulte:

Voltar

Integração comfoguetes

Nesta página