You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
fast-insiders/server/src/db/paginate.rs

104 lines
2.5 KiB

use sea_orm::{
error::DbErr, prelude::*, sea_query::SimpleExpr, FromQueryResult, ItemsAndPagesNumber, Order,
QueryOrder,
};
use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PaginatedResponse<M> {
pub count: u64,
pub num_pages: u64,
pub list: Vec<M>,
}
pub async fn paginate<E, M, C>(
db: &DatabaseConnection,
page: Option<u64>,
size: Option<u64>,
column: Option<C>,
order: Option<Order>,
) -> Result<PaginatedResponse<M>, DbErr>
where
E: EntityTrait,
M: Send + Sync + FromQueryResult,
C: ColumnTrait,
{
let s = size.unwrap_or(20).min(50);
let selector;
if let (Some(col), Some(ord)) = (column, order) {
selector = E::find().order_by(col, ord);
} else {
selector = E::find();
}
let pages = selector.into_model().paginate(db, s);
let ItemsAndPagesNumber {
number_of_items: count,
number_of_pages: num_pages,
} = pages.num_items_and_pages().await?;
let p = page.unwrap_or(0).min(num_pages);
let list = pages.fetch_page(p).await?;
let res = PaginatedResponse {
count,
num_pages,
list,
};
Ok(res)
}
/// Use for 1-1 relationships, retrieves the entity and the single related record
pub async fn paginate_also_related<E, R, T, K, C>(
db: &DatabaseConnection,
page: Option<u64>,
size: Option<u64>,
column: Option<C>,
order: Option<Order>,
filters: Option<Vec<SimpleExpr>>,
) -> Result<PaginatedResponse<(T, Option<K>)>, DbErr>
where
E: EntityTrait + Related<R>,
R: EntityTrait,
T: Sync + Send + FromQueryResult,
K: Sync + Send + FromQueryResult,
C: ColumnTrait,
{
let s = size.unwrap_or(20).min(50);
let mut selector;
if let (Some(col), Some(ord)) = (column, order) {
selector = E::find()
.find_also_related::<R>(R::default())
.order_by(col, ord)
} else {
selector = E::find().find_also_related::<R>(R::default());
}
if let Some(fils) = filters {
for fil in fils {
selector = selector.filter(fil);
}
}
let pages = selector.into_model().paginate(db, s);
let ItemsAndPagesNumber {
number_of_items: count,
number_of_pages: num_pages,
} = pages.num_items_and_pages().await?;
let p = page.unwrap_or(0).min(num_pages);
let list = pages.fetch_page(p).await?;
let res = PaginatedResponse {
count,
num_pages,
list,
};
Ok(res)
}