Learn the "why" behind slow queries and how to fix them in our 2-Part Webinar.
Register now >
Menu Docs
Página inicial do Docs
/ /

Integre o MongoDB com o Atix

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_restaurants

  • Expõe um /restaurants ponto de extremidade que lista todos os restaurantes

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

  • Renderiza 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 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.

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 uma localização segura. 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 do 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 driver para facilitar a observabilidade.

  • Cria um cliente e retorna um lidar 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 pontos de extremidade /restaurants e /browse.

  • Chama os serviços de query 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 ponto de extremidade /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 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.

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 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)}))
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 de Browse filtro 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 aplicativo da web Atix que se conecta à implantaçã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