chore: update query list

This commit is contained in:
Maulana Sodiqin
2025-05-20 16:57:45 +07:00
parent 055ef6ac8e
commit d906fc4747
18 changed files with 165 additions and 1139 deletions
+101 -63
View File
@@ -1,78 +1,116 @@
use super::{ListQueryBuilder, bind_filter_value};
use crate::{CountResult, MetaRequestDto, MetaResponseDto, ResponseListSuccessDto};
use anyhow::Result;
use serde::{Serialize, de::DeserializeOwned};
use surrealdb::{Surreal, engine::remote::ws::Client};
pub async fn query_list_with_meta<T>(
db: &Surreal<Client>,
table: &str,
meta: &MetaRequestDto,
pub struct QueryListBuilder<'a> {
db: &'a Surreal<Client>,
table: &'a str,
meta: &'a MetaRequestDto,
conditions: Vec<String>,
custom_select: Option<String>,
search_field: &str,
select_fields: Option<Vec<&str>>,
fetch_fields: Option<Vec<&str>>,
) -> Result<ResponseListSuccessDto<Vec<T>>>
where
T: DeserializeOwned + Serialize,
{
let page = meta.page.unwrap_or(1).max(1);
let per_page = meta.per_page.unwrap_or(10).max(1);
let start = (page - 1) * per_page;
search_field: String,
select_fields: Option<Vec<&'a str>>,
fetch_fields: Option<Vec<&'a str>>,
}
let sql = custom_select.unwrap_or_else(|| {
ListQueryBuilder::from_meta(
impl<'a> QueryListBuilder<'a> {
pub fn new(
db: &'a Surreal<Client>,
table: &'a str,
meta: &'a MetaRequestDto,
) -> Self {
Self {
db,
table,
meta,
search_field,
select_fields,
fetch_fields,
conditions: vec![],
search_field: "name".to_string(),
select_fields: None,
fetch_fields: None,
}
}
pub fn search_field(mut self, field: &'a str) -> Self {
self.search_field = field.to_string();
self
}
pub fn select_fields(mut self, fields: Vec<&'a str>) -> Self {
self.select_fields = Some(fields);
self
}
pub fn fetch_fields(mut self, fields: Vec<&'a str>) -> Self {
self.fetch_fields = Some(fields);
self
}
pub fn with_condition(mut self, condition: &str) -> Self {
self.conditions.push(condition.to_string());
self
}
pub async fn build<T>(self) -> Result<ResponseListSuccessDto<Vec<T>>>
where
T: DeserializeOwned + Serialize,
{
let page = self.meta.page.unwrap_or(1).max(1);
let per_page = self.meta.per_page.unwrap_or(10).max(1);
let start = (page - 1) * per_page;
let sql = crate::ListQueryBuilder::from_meta(
self.table,
self.meta,
&self.search_field,
self.select_fields,
self.fetch_fields,
)
.build()
});
.build();
let mut query_exec = db.query(sql);
if let Some(search) = &meta.search {
if !search.is_empty() {
query_exec = query_exec.bind(("search", search.to_lowercase().clone()));
let mut query_exec = self.db.query(sql);
if let Some(search) = &self.meta.search {
if !search.is_empty() {
query_exec = query_exec.bind(("search", search.to_lowercase()));
}
}
}
if let Some(filter_val) = &meta.filter {
query_exec = bind_filter_value(query_exec, filter_val.clone());
}
query_exec = query_exec
.bind(("per_page", per_page))
.bind(("start", start));
let raw: Vec<T> = query_exec.await?.take(0)?;
let mut count_query = db.query(format!(
"SELECT count() FROM {} {}",
table,
if conditions.is_empty() {
String::new()
} else {
format!("WHERE {}", conditions.join(" AND "))
if let Some(filter_val) = &self.meta.filter {
query_exec = crate::bind_filter_value(query_exec, filter_val.clone());
}
));
if let Some(search) = &meta.search {
if !search.is_empty() {
count_query = count_query.bind(("search", search.clone()));
}
}
if let Some(filter_val) = &meta.filter {
count_query = bind_filter_value(count_query, filter_val.clone());
}
let count_result: Vec<CountResult> = count_query.await?.take(0)?;
let total = count_result.first().map(|c| c.count);
query_exec = query_exec
.bind(("per_page", per_page))
.bind(("start", start));
Ok(ResponseListSuccessDto {
data: raw,
meta: Some(MetaResponseDto {
page: Some(page),
per_page: Some(per_page),
total,
}),
})
let raw: Vec<T> = query_exec.await?.take(0)?;
let mut count_query = self.db.query(format!(
"SELECT count() FROM {} {}",
self.table,
if self.conditions.is_empty() {
"".into()
} else {
format!("WHERE {}", self.conditions.join(" AND "))
}
));
if let Some(search) = &self.meta.search {
if !search.is_empty() {
count_query = count_query.bind(("search", search.clone()));
}
}
if let Some(filter_val) = &self.meta.filter {
count_query = crate::bind_filter_value(count_query, filter_val.clone());
}
let count_result: Vec<CountResult> = count_query.await?.take(0)?;
let total = count_result.first().map(|c| c.count);
Ok(ResponseListSuccessDto {
data: raw,
meta: Some(MetaResponseDto {
page: Some(page),
per_page: Some(per_page),
total,
}),
})
}
}