我试图根据外部参数为order_by
指定不同的列。
这可行,但是很丑:
#[macro_use]
extern crate diesel;
use crate::diesel::prelude::*;
use diesel::pg::PgConnection;
mod schema {
table! {
items (id) {
id -> Int4,
name -> Text,
}
}
}
#[derive(Queryable, Debug)]
pub struct Item {
pub id: i32,
pub name: String,
}
fn load_items(conn: PgConnection, sort_prop: String, sort_dir: String) -> Vec<Item> {
use schema::items::dsl::*;
let mut query = items.into_boxed();
// ugly: duplicating condition by sort_dir and query.order_by() calls
query = match sort_prop.as_str() {
"name" => {
if sort_dir == "asc" {
query.order_by(name.asc())
} else {
query.order_by(name.desc())
}
}
_ => {
if sort_dir == "asc" {
query.order_by(id.asc())
} else {
query.order_by(id.desc())
}
}
};
query.load::<Item>(&conn).expect("Failed to load items")
}
fn main() {}
我的Cargo.toml有这个:
[dependencies]
diesel = { version = "1.4.3", features = ["postgres"] }
我只想按列而不是整个查询作为条件,例如:
use schema::items::dsl::*;
let mut column = match sort_prop.as_str() {
"name" => name,
_ => id // error: match arms have incompatible types
}
column = if sort_dir == "asc" {
column.asc()
} else {
column.desc()
}
let results = items
.order_by(column)
.load::<Item>(connection)
.expect("Failed to load items");
这可能吗?还有其他方法可以重构吗?
我已经读过Querying a Diesel table with dynamic parameters,但这基本上是关于整个查询的条件处理,这是我要避免的事情。
我还读过Creating Diesel.rs queries with a dynamic number of .and()'s,它是关于通过过滤器进行调节的。这可能与我使用order_by
所需要的接近,但是我很难将BoxableExpression
的怪异性应用于我的案例,因为在文档中缺少关于我的确切案例的好的示例,也缺乏RLS支持在我的IDE中显示任何schema::items::dsl::*
类型,因此我可以自己浏览。
答案 0 :(得分:0)
给出以下架构:
table! {
flights (id) {
id -> Int4,
name -> Text,
country -> Text,
launch_date -> Timestamptz,
}
}
以及以下包含排序选项的结构:
pub struct SearchFlight {
pub sort: Option<String>,
pub sort_dir: Option<String>
}
可以实现以下目的:
let mut query = flights.into_boxed();
match search.sort.as_ref().map(String::as_str) {
Some("name") => sort_by_column(query, flights_schema::name, search.sort_dir),
Some("country") => sort_by_column(query, flights_schema::country, search.sort_dir),
Some("launch_date") => sort_by_column(query, flights_schema::launch_date, search.sort_dir),
_ => query
}
query.load_page::<Flight>(con)
如果有以下功能,则为sort_by_column
fn sort_by_column<U: 'static>(mut query: BoxedQuery<'static, Pg>,
column: U,
sort_dir: Option<String>) -> BoxedQuery<'static, Pg>
where U: ExpressionMethods + QueryFragment<Pg> + AppearsOnTable<flights_schema::table>{
match sort_dir.as_ref().map(String::as_str) {
Some("asc") => query.order_by(column.asc()),
Some("desc") => query.order_by(column.desc()),
_ => query
}
}