如何根据 Diesel 的动态参数有条件地按列排序?
Posted
技术标签:
【中文标题】如何根据 Diesel 的动态参数有条件地按列排序?【英文标题】:How do I conditionally order by a column based on a dynamic parameter with Diesel? 【发布时间】:2020-04-05 01:04:57 【问题描述】:我正在尝试根据外部参数为 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::*
类型,这样我就可以自己打乱了。
【问题讨论】:
把 if 放在最上面并在每个手臂上做一个匹配应该节省一些行 【参考方案1】:给定以下架构:
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)
where sort_by_column if 以下函数
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
【讨论】:
以上是关于如何根据 Diesel 的动态参数有条件地按列排序?的主要内容,如果未能解决你的问题,请参考以下文章