Working with Databases in Rust: PostgreSQL and MongoDB

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Introduction: Why Rust and databases are the perfect combination

Rust is a modern systems programming language that combines the performance of C/C++ with memory safety guaranteed by the compiler. When developing backend services, web applications, and microservices, there is almost always a need to interact with databases. In this article, we will thoroughly examine how to work with two of the most popular types of databases: relational PostgreSQL and document-oriented MongoDB.

We will cover connection, performing CRUD operations, transactions, and aggregations with practical examples. All code examples are written in Rust using the tokio async runtime, which provides maximum performance.



1. Project setup and dependency installation

First, let's create a new project and add the necessary crates. Open a terminal and run:

cargo new rust_db_examplecd rust_db_example

Add dependencies to the Cargo.toml file:

[dependencies]tokio = { version = "1", features = ["full"] }sqlx = { version = "0.7", features = ["runtime-tokio-rustls", "postgres"] }mongodb = "2.8"serde = { version = "1.0", features = ["derive"] }serde_json = "1.0"chrono = { version = "0.4", features = ["serde"] }

Now the project structure is ready. We will use sqlx for PostgreSQL — an async driver with support for compile-time checked queries, and the official mongodb driver for working with MongoDB.



1.1. Connecting to PostgreSQL via sqlx

Let's write a module for working with PostgreSQL. Create the file src/postgres.rs:

use sqlx::postgres::PgPoolOptions;use sqlx::PgPool;use anyhow::Result;

pub async fn connect_to_postgres() -> Result<PgPool> { let database_url = "postgres://user:password@localhost:5432/mydb"; let pool = PgPoolOptions::new() .max_connections(5) .connect(database_url) .await?; println!("✅ Connected to PostgreSQL"); Ok(pool)}

// Define the user model#[derive(Debug, sqlx::FromRow)]pub struct User { pub id: i32, pub name: String, pub email: String, pub created_at: chrono::NaiveDateTime,}


1.2. Connecting to MongoDB

Create the file src/mongodb.rs:

use mongodb::{Client, Collection, Database};use mongodb::bson::{doc, Document};use anyhow::Result;

pub async fn connect_to_mongodb() -> Result<(Database, Collection<Document>)> { let client = Client::with_uri_str("mongodb://localhost:27017")?; let database = client.database("mydb"); let collection = database.collection::<Document>("users"); println!("✅ Connected to MongoDB"); Ok((database, collection))}


2. CRUD operations in PostgreSQL

Now let's implement the basic operations: creating, reading, updating, and deleting records.



2.1. Inserting data (CREATE)

pub async fn create_user(pool: &PgPool, name: &str, email: &str) -> Result<User> {    let user = sqlx::query_as::<_, User>(        "INSERT INTO users (name, email) VALUES ($1, $2) RETURNING id, name, email, created_at"    )    .bind(name)    .bind(email)    .fetch_one(pool)    .await?;        println!("Created user: {:?}", user);    Ok(user)}


2.2. Reading data (READ)

pub async fn get_user_by_id(pool: &PgPool, user_id: i32) -> Result<Option<User>> {    let user = sqlx::query_as::<_, User>(        "SELECT id, name, email, created_at FROM users WHERE id = $1"    )    .bind(user_id)    .fetch_optional(pool)    .await?;        match user {        Some(u) => println!("Found user: {:?}", u),        None => println!("User with id={} not found"                

Blogs

Book Recommendations