You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将含NOT IN的PostgreSQL查询转换为Diesel查询?

在Diesel中实现"NOT IN"子查询获取用户未达成的成就

我有achievements和user_achievements两张表,结构如下:

achievements
--------------
| id | name  |
|  1 | one   |
|  2 | two   |
|  3 | three |
--------------

user_achievements
---------------------------------
| id | user_id | achievement_id |
|  1 |       1 |              1 |
|  2 |       1 |              2 |
|  3 |       2 |              3 |
---------------------------------

用PostgreSQL写的目标查询(获取指定用户未达成的成就):

SELECT a.* FROM achievements as a
WHERE a.id NOT IN (SELECT ua.achievement_id FROM user_achievements as ua WHERE user_id = 2);

查询结果:

--------------
| id | name  |
|  1 | one   |
|  2 | two   |
--------------

尝试转成Diesel代码时遇到问题:找不到类似not_eq_any的方法,最初的实现代码:

pub fn get_achievements_not_achieved_by_user(&self, the_user_id: i32) -> QueryResult<Vec<Achievement>> {
    let conn = &mut self.pool.get().unwrap();
    achievements.filter(!id.eq_any(user_achievements.select(achievement_id).filter(user_id.eq(the_author_id)))).get_results(conn)
}

解决方法

Diesel没有直接的not_eq_any,但有两种方式实现需求:

方式一:使用ne_all方法(推荐,语义更清晰)

ne_all对应SQL里的NOT IN,直接用它来筛选不在子查询结果里的记录,同时要修正你代码里的变量名错误(the_author_id应该是参数the_user_id):

pub fn get_achievements_not_achieved_by_user(&self, the_user_id: i32) -> QueryResult<Vec<Achievement>> {
    let conn = &mut self.pool.get().unwrap();
    // 先获取该用户已解锁的成就ID集合
    let achieved_ids = user_achievements
        .select(achievement_id)
        .filter(user_id.eq(the_user_id));
    
    // 筛选出未解锁的成就
    achievements
        .filter(id.ne_all(achieved_ids))
        .get_results(conn)
}

方式二:对eq_any取反

和你最初的思路一致,只要修正变量名错误即可:

pub fn get_achievements_not_achieved_by_user(&self, the_user_id: i32) -> QueryResult<Vec<Achievement>> {
    let conn = &mut self.pool.get().unwrap();
    achievements
        .filter(!id.eq_any(user_achievements.select(achievement_id).filter(user_id.eq(the_user_id))))
        .get_results(conn)
}

注意点

  • 你原来的代码里把参数the_user_id误写为the_author_id,这会导致编译错误或者逻辑错误,必须修正。
  • ne_all是Diesel专门为NOT IN场景提供的API,可读性比取反eq_any更好,更推荐使用。

内容的提问来源于stack exchange,提问作者Manuelarte

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.21 10:44:53