Rust 中的数据库操作:PostgreSQL 与 MongoDB

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

介绍:为什么Rust和数据库是完美组合

Rust是一种现代系统编程语言,它将C/C++的性能与编译器保证的内存安全性结合在一起。在开发后端服务、Web应用程序和微服务时,几乎总是需要与数据库进行交互。在本文中,我们将详细讨论如何与两种最流行的数据库类型一起工作:关系型PostgreSQL和文档型MongoDB。

我们将通过实际示例介绍连接、执行CRUD操作、事务和聚合。所有代码示例都使用Rust编写,并采用异步运行时tokio,以实现最大性能。

1. 项目设置和依赖安装

首先,创建一个新项目并添加必要的crate。打开终端并执行:

cargo new rust_db_example
cd rust_db_example

在Cargo.toml文件中添加依赖:

[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"] }

现在项目结构已准备就绪。我们将使用sqlx连接PostgreSQL——这是一个支持编译时查询检查的异步驱动程序,以及官方mongodb驱动程序来操作MongoDB。

1.1. 通过sqlx连接PostgreSQL

编写一个用于操作PostgreSQL的模块。创建文件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!("✅ 已连接到PostgreSQL");
    Ok(pool)
}

// 定义用户模型
#[derive(Debug, sqlx::FromRow)]
pub struct User {
    pub id: i32,
    pub name: String,
    pub email: String,
    pub created_at: chrono::NaiveDateTime,
}

1.2. 连接MongoDB

创建文件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!("✅ 已连接到MongoDB");
    Ok((database, collection))
}

2. PostgreSQL中的CRUD操作

现在实现基本操作:创建、读取、更新和删除记录。

2.1. 插入数据 (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!("已创建用户: {:?}", user);
    Ok(user)
}

2.2. 读取数据 (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!("找到用户: {:?}", u),
        None => println!("未找到id={}的用户"                

博客

书籍推荐