Diesel DSL 常用方法详解及注释示例

Diesel DSL 常用方法详解及注释示例

Diesel DSL 常用方法详解及注释示例

一、基础查询构建

1.1 SELECT 查询


// 导入Diesel核心模块和查询DSL

use diesel::prelude::*;                      // Diesel ORM核心功能导入

use diesel::dsl::count;                      // 导入计数聚合函数



// 基础查询示例 - 获取所有已发布文章

let posts = posts::table                     // 指定查询的表(posts表)

    .filter(posts::status.eq(PostStatus::Published.as_i32()))  // 过滤条件:状态为已发布

    .filter(posts::is_deleted.eq(false))     // 过滤条件:未删除的记录

    .order_by(posts::created_at.desc())      // 排序条件:按创建时间降序

    .limit(10)                               // 限制返回结果数量为10条

    .offset(0)                               // 偏移量为0(从第一条开始)

    .load::<Post>(conn)                      // 执行查询并转换为Post类型的向量

    .map_err(|e| format!("查询失败: {:?}", e))?;  // 错误处理:将Diesel错误转换为字符串

1.2 计数查询


// 获取已发布文章总数

let total_count: i64 = posts::table          // 指定查询的表(posts表)

    .filter(posts::status.eq(Some(PostStatus::Published.as_i32())))  // 状态为已发布

    .filter(posts::is_deleted.eq(false))     // 未删除的记录

    .select(count(posts::id))                // 选择计数字段(按id计数)

    .first(conn)                             // 获取查询结果的第一个值

    .map_err(|_| "数据库连接失败".to_string())?;  // 错误处理

二、数据操作

2.1 INSERT 插入


// 创建新文章

let new_post = NewPost {

    title: "Diesel DSL教程".to_string(),       // 文章标题

    content: "详细介绍Diesel的使用方法".to_string(),  // 文章内容

    status: Some(PostStatus::Draft.as_i32()), // 状态:草稿

    author_id: user_id,                       // 作者ID

    created_at: Utc::now().naive_utc(),       // 创建时间

    updated_at: Utc::now().naive_utc(),       // 更新时间

    is_deleted: false,                        // 未删除

};



// 执行插入操作

let inserted_post = diesel::insert_into(posts::table)  // 指定插入目标表

    .values(&new_post)                         // 指定插入的值

    .get_result(conn)                          // 返回插入后的完整记录

    .map_err(|e| format!("插入失败: {:?}", e))?;  // 错误处理

2.2 UPDATE 更新


// 更新文章状态

let updated_post = diesel::update(posts::table.filter(posts::id.eq(post_id)))  // 指定更新条件

    .set((                                    // 设置更新字段

        posts::status.eq(PostStatus::Published.as_i32()),  // 状态改为已发布

        posts::updated_at.eq(Utc::now().naive_utc()),      // 更新时间

    ))

    .get_result::<Post>(conn)                 // 返回更新后的记录

    .map_err(|_| "更新失败".to_string())?;      // 错误处理

2.3 DELETE 删除(逻辑删除)


// 逻辑删除文章(设置is_deleted=true)

diesel::update(posts::table.filter(posts::id.eq(post_id)))  // 指定更新条件

    .set(posts::is_deleted.eq(true))          // 设置删除标记

    .execute(conn)                            // 执行更新操作(返回受影响行数)

    .map_err(|_| "删除失败".to_string())?;      // 错误处理

三、高级查询

3.1 关联查询


// 查询文章及其分类

let post_with_categories = posts::table

    .inner_join(post_category_relations::table)  // 内连接分类关系表

    .inner_join(post_category_types::table)      // 内连接分类表

    .filter(posts::id.eq(post_id))               // 过滤指定文章ID

    .select((                                    // 选择需要的字段

        posts::all_columns,                      // 文章表所有字段

        post_category_types::name,               // 分类名称

    ))

    .load(conn)                                  // 执行查询

    .map_err(|_| "关联查询失败".to_string())?;    // 错误处理

3.2 聚合查询


// 按分类统计文章数量

let category_counts = post_category_types::table

    .left_join(post_category_relations::table)   // 左连接分类关系表

    .left_join(posts::table.on(posts::is_deleted.eq(false)))  // 左连接未删除文章

    .group_by(post_category_types::id)           // 按分类ID分组

    .select((                                    // 选择分类ID、名称和计数

        post_category_types::id,

        post_category_types::name,

        count(posts::id).nullable(),            // 允许计数为NULL(没有文章的分类)

    ))

    .load(conn)

    .map_err(|_| "聚合查询失败".to_string())?;    // 错误处理

四、事务处理


// 使用事务确保操作原子性

let result = conn.transaction(|| {

    // 步骤1: 创建文章

    let post = diesel::insert_into(posts::table)

        .values(&new_post)

        .get_result::<Post>(conn)?;



    // 步骤2: 关联分类

    let category_relations = category_ids.iter()

        .map(|&category_id| NewPostCategoryRelation {

            post_id: post.id,

            category_id,

        })

        .collect::<Vec<_>>();



    diesel::insert_into(post_category_relations::table)

        .values(&category_relations)

        .execute(conn)?;



    Ok(post)

}).map_err(|e| format!("事务失败: {:?}", e))?;  // 事务错误处理

五、常用方法速查表

| 方法名 | 作用 | 示例 |

| -------------- | ------------------ | ------------------------------------ |

| filter() | 添加查询条件 | filter(posts::id.eq(1)) |

| order_by() | 设置排序方式 | order_by(posts::created_at.desc()) |

| limit() | 限制结果数量 | limit(10) |

| offset() | 设置偏移量(分页) | offset(20) |

| select() | 指定返回字段 | select((posts::id, posts::title)) |

| inner_join() | 内连接表 | inner_join(comments::table) |

| group_by() | 分组查询 | group_by(posts::author_id) |

| count() | 计数聚合 | count(posts::id) |

| eq() | 等于条件 | posts::status.eq(1) |

| ne() | 不等于条件 | posts::is_deleted.ne(true) |

| like() | 模糊查询 | posts::title.like("%Diesel%") |

| and() | 条件与操作 | filter(a.eq(1).and(b.eq(2))) |

| or() | 条件或操作 | filter(a.eq(1).or(b.eq(2))) |

六、代码注释规范说明

  1. 模块导入注释:说明导入模块的用途和包含的主要功能

  2. 查询构建注释:每行查询方法前添加说明其作用的注释

  3. 条件说明:对过滤条件、连接条件等添加业务逻辑说明

  4. 错误处理注释:说明可能的错误类型和处理方式

  5. 返回值注释:说明查询返回的具体数据结构和含义

通过以上规范,可以使代码更易于维护和理解,特别是在复杂的数据库查询场景中。


本文由萧兮的博客原创发布,欢迎转载,转载务必保留原文链接。

萧兮的博客https://www.20010515.xyz · 原文:https://www.20010515.xyz/posts/165a0a38-f077-4d4e-8239-f164ab12ecc8