如何为Diesel ORM创建查询条件通用函数?求解返回类型
解决Diesel ORM复用查询条件的返回类型问题
方案1:用impl Trait返回抽象类型
Diesel的查询构建器会生成复杂的匿名类型,手动写具体类型太折腾。Rust的impl Trait可以直接返回满足指定trait约束的类型,不用纠结具体泛型参数。
直接修改通用函数:
use diesel::query_dsl::{QueryDsl, FilterDsl}; use diesel::pg::Pg; // 用其他数据库的话换成对应模块,比如Sqlite fn get_conditions() -> impl QueryDsl + FilterDsl<posts::Table> + diesel::query_source::AppearsInFromClause<posts::Table, Pg> { posts.filter(title.eq("mark")).filter(body.eq("good")) }
之后在count和list里直接调用就行:
fn count() -> i64 { get_conditions().count().get_result(&mut con).expect("error") } fn list() -> Vec<Posts> { get_conditions().load::<Posts>(&mut con).expect("error") }
这里的trait约束保证返回的类型能支持后续的count()和load()操作,记得根据你用的数据库调整对应的trait(比如PostgreSQL用Pg,SQLite用Sqlite)。
方案2:推导具体类型+类型别名
如果需要明确的类型(比如要放到结构体字段里),可以让编译器帮你推导:
- 先写个临时函数,故意写错返回类型,逼编译器吐出正确类型:
fn temp() -> () { posts.filter(title.eq("mark")).filter(body.eq("good")) }
编译时会看到类似这样的错误提示,里面就是我们要的具体类型:
expected `()`, found struct `diesel::query_builder::Filter<diesel::query_builder::Filter<posts::table, diesel::expression::operators::Eq<posts::title, diesel::expression::bound::Bound<diesel::sql_types::Varchar, &str>>>, diesel::expression::operators::Eq<posts::body, diesel::expression::bound::Bound<diesel::sql_types::Text, &str>>>`
- 把这个长类型复制出来,用类型别名简化:
type FilteredPostsQuery = diesel::query_builder::Filter< diesel::query_builder::Filter< posts::Table, diesel::expression::operators::Eq<posts::title, diesel::expression::bound::Bound<diesel::sql_types::Varchar, &str>> >, diesel::expression::operators::Eq<posts::body, diesel::expression::bound::Bound<diesel::sql_types::Text, &str>> >;
- 然后用这个别名当返回类型:
fn get_conditions() -> FilteredPostsQuery { posts.filter(title.eq("mark")).filter(body.eq("good")) }
这种方式的缺点是类型字符串巨长,而且只要修改查询条件,类型就会变,得重新推导。
额外提醒
- 你的示例里用了单引号
'mark',这在Rust里是字符字面量,会导致类型不匹配,要改成双引号的字符串"mark"。 - 确保导入了Diesel的prelude和对应数据库的必要模块。
内容的提问来源于stack exchange,提问作者vishnukvnvv
相关产品推荐
相关产品推荐

