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))) |
六、代码注释规范说明
-
模块导入注释:说明导入模块的用途和包含的主要功能
-
查询构建注释:每行查询方法前添加说明其作用的注释
-
条件说明:对过滤条件、连接条件等添加业务逻辑说明
-
错误处理注释:说明可能的错误类型和处理方式
-
返回值注释:说明查询返回的具体数据结构和含义
通过以上规范,可以使代码更易于维护和理解,特别是在复杂的数据库查询场景中。
本文由萧兮的博客原创发布,欢迎转载,转载务必保留原文链接。
萧兮的博客:https://www.20010515.xyz · 原文:https://www.20010515.xyz/posts/165a0a38-f077-4d4e-8239-f164ab12ecc8