Working with Databases in Rust: PostgreSQL and MongoDB for Beginners

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

Working with Databases in Rust: PostgreSQL and MongoDB for Beginners

\n\n

Rust is a modern systems programming language that is gaining popularity due to its performance and safety. But how do you work with databases in Rust? In this article, we will cover connecting to and performing basic operations with two popular DBMS: relational PostgreSQL and document-oriented MongoDB. The material is intended for beginner developers familiar with the basics of Rust.

\n\n

Why Rust and Databases are a Good Combination?

\n\n

Rust offers a strict type system and memory safety guarantees, which is especially valuable when working with data. Memory access errors typical of C/C++ are eliminated at compile time. Additionally, the Rust ecosystem includes mature libraries for interacting with databases: diesel for PostgreSQL and the official driver for MongoDB.

\n\n

In this article, we will learn how to:

\n
    \n
  • Connect to PostgreSQL and MongoDB from Rust
  • \n
  • Perform CRUD operations (Create, Read, Update, Delete)
  • \n
  • Work with query results safely and efficiently
  • \n
\n\n

1. Working with PostgreSQL using the Diesel Library

\n\n

Diesel is an ORM and query builder for Rust that provides type safety at the compile level. To get started, add dependencies to Cargo.toml:

\n\n
[dependencies]\ndiesel = { version = "2.1", features = ["postgres"] }\ndotenvy = "0.15"\nserde = { version = "1.0", features = ["derive"] }\nserde_json = "1.0"\ntokio = { version = "1.0", features = ["full"] }
\n\n

Setting up the Connection

\n\n

Create a .env file with your database URL:

\n\n
DATABASE_URL=postgres://user:password@localhost/mydb
\n\n

Now let's write the code to connect and create a table:

\n\n
use diesel::prelude::*;\nuse diesel::pg::PgConnection;\nuse dotenvy::dotenv;\nuse std::env;\n\npub fn establish_connection() -> PgConnection {\n    dotenv().ok();\n    let database_url = env::var("DATABASE_URL")\n        .expect("DATABASE_URL must be set");\n    PgConnection::establish(&database_url)\n        .unwrap_or_else(|_| panic!("Error connecting to {}", database_url))\n}
\n\n

Defining the Schema and Model

\n\n

Let's create a users table and a corresponding Rust model:

\n\n
// schema.rs\ntable! {\n    users (id) {\n        id -> Int4,\n        name -> Varchar,\n        email -> Varchar,\n        created_at -> Timestamp,\n    }\n}\n\n// models.rs\n#[derive(Queryable, Selectable)]\n#[diesel(table_name = crate::schema::users)]\n#[diesel(check_for_backend(diesel::pg::Pg))]\npub struct User {\n    pub id: i32,\n    pub name: String,\n    pub email: String,\n    pub created_at: chrono::NaiveDateTime,\n}\n\n#[derive(Insertable)]\n#[diesel(table_name = crate::schema::users)]\npub struct NewUser {\n    pub name: String,\n    pub email: String,\n}
\n\n

CRUD Operations

\n\n

Example of creating and reading users:

\n\n
use crate::models::{User, NewUser};\nuse crate::schema::users;\n\npub fn create_user(conn: &mut PgConnection, name: &str, email: &str) -> User {\n    let new_user = NewUser {\n        name: name.to_string(),\n        email: email.to_string(),\n    };\n\n    diesel::insert_into(users::table)\n        .values(&new_user)\n        .returning(User::as_returning())\n        .get_result(conn)\n        .expect("Error saving new user")\n}\n\npub fn get_all_users(conn: &mut PgConnection) -> Vec {\n    users::table\n        .load::(conn)\n        .expect("Error loading users")\n}
\n\n

As you can see, Diesel checks types and column names at compile time. An error in a field name will result in a compile-time error, not a runtime failure.

\n\n

2. Working with MongoDB using the Official Driver

\n\n

MongoDB is a NoSQL database that stores data in a JSON-like format

Blogs

Book Recommendations