feat: some experimentation with api filtering

concurrent-repos
Jef Roosens 2024-05-21 08:49:46 +02:00
parent e684cfb84e
commit e1642d939b
Signed by: Jef Roosens
GPG Key ID: B75D4F293C7052DB
6 changed files with 68 additions and 16 deletions

View File

@ -1,5 +1,7 @@
mod pagination;
use sea_orm::{sea_query::IntoCondition, *};
use axum::extract::{Path, Query, State};
use axum::routing::get;
use axum::Json;
@ -7,7 +9,7 @@ use axum::Router;
use pagination::PaginatedResponse;
use crate::db;
use crate::db::{self, *};
pub fn router() -> Router<crate::Global> {
Router::new()
@ -20,16 +22,27 @@ pub fn router() -> Router<crate::Global> {
async fn get_repos(
State(global): State<crate::Global>,
Query(pagination): Query<pagination::Query>,
Query(filter): Query<db::query::repo::Filter>,
) -> crate::Result<Json<PaginatedResponse<db::repo::Model>>> {
let (total_pages, repos) = global
.db
.repo
.page(
pagination.per_page.unwrap_or(25),
pagination.page.unwrap_or(1) - 1,
)
let page = pagination.page.unwrap_or(1) - 1;
let per_page = pagination.per_page.unwrap_or(25);
let paginator = Repo::find()
.filter(filter)
.order_by_asc(package::Column::Id)
.paginate(&global.db, pagination.per_page.unwrap_or(25));
let items = paginator
.fetch_page(pagination.page.unwrap_or(1) - 1)
.await?;
Ok(Json(pagination.res(total_pages, repos)))
let total_pages = paginator.num_pages().await?;
Ok(Json(PaginatedResponse {
page,
per_page,
total_pages,
count: items.len(),
items,
}))
}
async fn get_single_repo(
@ -49,6 +62,7 @@ async fn get_single_repo(
async fn get_packages(
State(global): State<crate::Global>,
Query(pagination): Query<pagination::Query>,
Query(filter): Query<db::query::package::Filter>,
) -> crate::Result<Json<PaginatedResponse<db::package::Model>>> {
let (total_pages, pkgs) = global
.db
@ -56,6 +70,7 @@ async fn get_packages(
.page(
pagination.per_page.unwrap_or(25),
pagination.page.unwrap_or(1) - 1,
filter,
)
.await?;

View File

@ -1,6 +1,6 @@
use serde::{Deserialize, Serialize};
pub const DEFAULT_PAGE: u64 = 0;
pub const DEFAULT_PAGE: u64 = 1;
pub const DEFAULT_PER_PAGE: u64 = 25;
#[derive(Deserialize)]

View File

@ -1,7 +1,7 @@
mod conn;
pub mod entities;
mod migrator;
mod query;
pub mod query;
use sea_orm::{ConnectOptions, Database, DatabaseConnection, DeriveActiveEnum, EnumIter};
use sea_orm_migration::MigratorTrait;
@ -14,6 +14,7 @@ type Result<T> = std::result::Result<T, sea_orm::DbErr>;
#[derive(EnumIter, DeriveActiveEnum, Serialize, Deserialize, PartialEq, Eq, Clone, Debug)]
#[sea_orm(rs_type = "i32", db_type = "Integer")]
#[serde(rename_all = "lowercase")]
pub enum PackageRelatedEnum {
#[sea_orm(num_value = 0)]
Conflicts,

View File

@ -1,5 +1,5 @@
mod package;
mod repo;
pub mod package;
pub mod repo;
pub use package::PackageQuery;
pub use repo::RepoQuery;

View File

@ -1,4 +1,5 @@
use sea_orm::*;
use sea_orm::{sea_query::IntoCondition, *};
use serde::Deserialize;
use crate::db::*;
@ -7,6 +8,25 @@ pub struct PackageQuery {
conn: DatabaseConnection,
}
#[derive(Deserialize)]
pub struct Filter {
repo: Option<i32>,
arch: Option<String>,
name: Option<String>,
}
impl IntoCondition for Filter {
fn into_condition(self) -> Condition {
Condition::all()
.add_option(self.repo.map(|repo| package::Column::RepoId.eq(repo)))
.add_option(self.arch.map(|arch| package::Column::Arch.eq(arch)))
.add_option(
self.name
.map(|name| package::Column::Name.like(format!("%{}%", name))),
)
}
}
impl PackageQuery {
pub fn new(conn: DatabaseConnection) -> Self {
Self { conn }
@ -16,8 +36,10 @@ impl PackageQuery {
&self,
per_page: u64,
page: u64,
filter: Filter,
) -> super::Result<(u64, Vec<package::Model>)> {
let paginator = Package::find()
.filter(filter)
.order_by_asc(package::Column::Id)
.paginate(&self.conn, per_page);
let packages = paginator.fetch_page(page).await?;
@ -132,7 +154,10 @@ impl PackageQuery {
package_id: Set(pkg_entry.id),
r#type: Set(t),
name: Set(s.to_string()),
}));
}))
.on_empty_do_nothing()
.exec(&self.conn)
.await?;
PackageFile::insert_many(pkg.files.iter().map(|s| package_file::ActiveModel {
package_id: Set(pkg_entry.id),

View File

@ -1,4 +1,4 @@
use sea_orm::*;
use sea_orm::{sea_query::IntoCondition, *};
use crate::db::*;
@ -7,6 +7,17 @@ pub struct RepoQuery {
conn: DatabaseConnection,
}
#[derive(Deserialize)]
pub struct Filter {
name: Option<String>,
}
impl IntoCondition for Filter {
fn into_condition(self) -> Condition {
Condition::all().add_option(self.name.map(|name| package::Column::Name.like(name)))
}
}
impl RepoQuery {
pub fn new(conn: DatabaseConnection) -> Self {
Self { conn }