Skip to content

Commit fda8dbf

Browse files
authored
feat: search add len query OP (#768)
* feat: search add len query OP * update * update
1 parent b1b7ed0 commit fda8dbf

File tree

8 files changed

+54
-26
lines changed

8 files changed

+54
-26
lines changed

backend/basic/src/dto.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -81,17 +81,15 @@ impl BasicQueryCondInfo {
8181
false
8282
}
8383
}
84-
BasicQueryOpKind::Like => {
85-
check_val.as_str().map(|check_val_str| cond.value.as_str().map(|cond_val_str| check_val_str.contains(cond_val_str)).unwrap_or(false)).unwrap_or(false)
86-
}
87-
BasicQueryOpKind::NotLike => {
84+
BasicQueryOpKind::Like | BasicQueryOpKind::LLike | BasicQueryOpKind::RLike | BasicQueryOpKind::NotLike => {
8885
check_val.as_str().map(|check_val_str| cond.value.as_str().map(|cond_val_str| check_val_str.contains(cond_val_str)).unwrap_or(false)).unwrap_or(false)
8986
}
9087
BasicQueryOpKind::In => check_val.as_array().map(|check_val_arr| check_val_arr.contains(&cond.value)).unwrap_or(false),
9188
BasicQueryOpKind::NotIn => check_val.as_array().map(|check_val_arr| check_val_arr.contains(&cond.value)).unwrap_or(false),
9289
BasicQueryOpKind::IsNull => false,
9390
BasicQueryOpKind::IsNotNull => false,
9491
BasicQueryOpKind::IsNullOrEmpty => false,
92+
BasicQueryOpKind::Len => false,
9593
},
9694
None => false,
9795
})

backend/basic/src/enumeration.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,10 @@ pub enum BasicQueryOpKind {
6262
Le,
6363
#[oai(rename = "like")]
6464
Like,
65+
#[oai(rename = "l_like")]
66+
LLike,
67+
#[oai(rename = "r_like")]
68+
RLike,
6569
#[oai(rename = "not_like")]
6670
NotLike,
6771
#[oai(rename = "in")]
@@ -74,6 +78,8 @@ pub enum BasicQueryOpKind {
7478
IsNotNull,
7579
#[oai(rename = "is_null_or_empty")]
7680
IsNullOrEmpty,
81+
#[oai(rename = "length")]
82+
Len,
7783
}
7884

7985
impl BasicQueryOpKind {
@@ -86,12 +92,15 @@ impl BasicQueryOpKind {
8692
BasicQueryOpKind::Lt => "<".to_string(),
8793
BasicQueryOpKind::Le => "<=".to_string(),
8894
BasicQueryOpKind::Like => "LIKE".to_string(),
95+
BasicQueryOpKind::LLike => "LIKE".to_string(),
96+
BasicQueryOpKind::RLike => "LIKE".to_string(),
8997
BasicQueryOpKind::NotLike => "NOT LIKE".to_string(),
9098
BasicQueryOpKind::In => "IN".to_string(),
9199
BasicQueryOpKind::NotIn => "NOT IN".to_string(),
92100
BasicQueryOpKind::IsNull => "IS NULL".to_string(),
93101
BasicQueryOpKind::IsNotNull => "IS NOT NULL".to_string(),
94102
BasicQueryOpKind::IsNullOrEmpty => "IS NULL".to_string(),
103+
BasicQueryOpKind::Len => "=".to_string(),
95104
}
96105
}
97106
}

backend/basic/src/helper/db_helper.rs

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,12 @@ use tardis::{
88
serde_json,
99
};
1010

11+
use crate::enumeration::BasicQueryOpKind;
12+
1113
/// Convert JSON value to SeaORM value.
1214
///
1315
/// When the JSON value is a string, you can specify whether to add % on both sides of the string through the ``like_by_str`` parameter.
14-
pub fn json_to_sea_orm_value(json_value: &serde_json::Value, like_by_str: bool) -> Option<Vec<sea_orm::Value>> {
16+
pub fn json_to_sea_orm_value(json_value: &serde_json::Value, like_kind: &BasicQueryOpKind) -> Option<Vec<sea_orm::Value>> {
1517
match json_value {
1618
serde_json::Value::Null => None,
1719
serde_json::Value::Bool(val) => Some(vec![sea_orm::Value::from(*val)]),
@@ -22,8 +24,12 @@ pub fn json_to_sea_orm_value(json_value: &serde_json::Value, like_by_str: bool)
2224
serde_json::Value::String(val) => match str_to_datetime(val) {
2325
Ok(val) => Some(vec![sea_orm::Value::from(val)]),
2426
Err(_) => {
25-
if like_by_str {
27+
if like_kind == &BasicQueryOpKind::Like || like_kind == &BasicQueryOpKind::NotLike {
2628
Some(vec![sea_orm::Value::from(format!("%{val}%"))])
29+
} else if like_kind == &BasicQueryOpKind::LLike {
30+
Some(vec![sea_orm::Value::from(format!("%{val}"))])
31+
} else if like_kind == &BasicQueryOpKind::RLike {
32+
Some(vec![sea_orm::Value::from(format!("{val}%"))])
2733
} else {
2834
Some(vec![sea_orm::Value::from(val)])
2935
}
@@ -35,7 +41,7 @@ pub fn json_to_sea_orm_value(json_value: &serde_json::Value, like_by_str: bool)
3541
return None;
3642
}
3743
// Convert each element in the array to SeaORM value.
38-
let vals = val.iter().map(|json| json_to_sea_orm_value(json, like_by_str)).collect::<Vec<Option<Vec<sea_orm::Value>>>>();
44+
let vals = val.iter().map(|json| json_to_sea_orm_value(json, like_kind)).collect::<Vec<Option<Vec<sea_orm::Value>>>>();
3945
if vals.iter().any(|v| v.is_none()) {
4046
warn!("[Basic] json_to_sea_orm_value: json array conversion failed.");
4147
return None;

backend/spi/spi-log/src/serv/pg/log_pg_item_serv.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -134,7 +134,7 @@ pub async fn find(find_req: &mut LogItemFindReq, funs: &TardisFunsInst, ctx: &Ta
134134
let err_op_in_without_value = || Err(funs.err().bad_request("item", "log", "Request item using 'IN' operator show hava a value", "400-spi-item-op-in-without-value"));
135135
if let Some(ext) = &find_req.ext {
136136
for ext_item in ext {
137-
let value = db_helper::json_to_sea_orm_value(&ext_item.value, ext_item.op == BasicQueryOpKind::Like);
137+
let value = db_helper::json_to_sea_orm_value(&ext_item.value, &ext_item.op);
138138
let Some(mut value) = value else {
139139
return err_notfound(ext_item);
140140
};
@@ -211,7 +211,7 @@ pub async fn find(find_req: &mut LogItemFindReq, funs: &TardisFunsInst, ctx: &Ta
211211
if let Some(ext_or) = &find_req.ext_or {
212212
let mut or_fragments = vec![];
213213
for ext_or_item in ext_or {
214-
let value = db_helper::json_to_sea_orm_value(&ext_or_item.value, ext_or_item.op == BasicQueryOpKind::Like);
214+
let value = db_helper::json_to_sea_orm_value(&ext_or_item.value, &ext_or_item.op);
215215

216216
let Some(mut value) = value else {
217217
return err_notfound(ext_or_item);
@@ -288,7 +288,7 @@ pub async fn find(find_req: &mut LogItemFindReq, funs: &TardisFunsInst, ctx: &Ta
288288
};
289289
if let Some(ext) = &group_query.ext {
290290
for ext_item in ext {
291-
let value = db_helper::json_to_sea_orm_value(&ext_item.value, ext_item.op == BasicQueryOpKind::Like || ext_item.op == BasicQueryOpKind::NotLike);
291+
let value = db_helper::json_to_sea_orm_value(&ext_item.value, &ext_item.op);
292292
let Some(mut value) = value else { return err_not_found(ext_item) };
293293
if ext_item.in_ext.unwrap_or(true) {
294294
if ext_item.op == BasicQueryOpKind::In {

backend/spi/spi-search/src/search_enumeration.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,7 @@ impl SearchDataTypeKind {
136136
Some(vec![value])
137137
}
138138
} else {
139-
db_helper::json_to_sea_orm_value(value, op == &BasicQueryOpKind::Like)
139+
db_helper::json_to_sea_orm_value(value, op)
140140
};
141141
let Some(mut value) = value else {
142142
return Err(TardisError::internal_error("json_to_sea_orm_value result is empty", "spi-stats-inaternal-error"));
@@ -206,7 +206,7 @@ impl SearchDataTypeKind {
206206
let value = self.json_to_sea_orm_value(value, op == &BasicQueryOpKind::Like)?;
207207
Some(vec![value])
208208
} else {
209-
db_helper::json_to_sea_orm_value(value, op == &BasicQueryOpKind::Like)
209+
db_helper::json_to_sea_orm_value(value, op)
210210
};
211211

212212
let Some(mut value) = value else {

backend/spi/spi-search/src/serv/es/search_es_item_serv.rs

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use std::collections::HashMap;
22

33
use tardis::{
4-
basic::{dto::TardisContext, result::TardisResult},
4+
basic::{dto::TardisContext, error::TardisError, result::TardisResult},
55
search::search_client::TardisSearchClient,
66
serde_json::{self, json, Value},
77
web::web_resp::TardisPage,
@@ -567,16 +567,11 @@ fn gen_query_dsl(search_req: &SearchItemSearchReq) -> TardisResult<String> {
567567
"range": {field: {"lte": cond_info.value.clone()}},
568568
}));
569569
}
570-
BasicQueryOpKind::Like => {
570+
BasicQueryOpKind::Like | BasicQueryOpKind::LLike | BasicQueryOpKind::RLike | BasicQueryOpKind::NotLike => {
571571
must_q.push(json!({
572572
"match": {field: cond_info.value.clone()}
573573
}));
574574
}
575-
BasicQueryOpKind::NotLike => {
576-
must_not_q.push(json!({
577-
"match": { field: cond_info.value.clone()}
578-
}));
579-
}
580575
BasicQueryOpKind::In => {
581576
let value = if cond_info.value.is_array() {
582577
cond_info.value.clone()
@@ -623,9 +618,16 @@ fn gen_query_dsl(search_req: &SearchItemSearchReq) -> TardisResult<String> {
623618
}
624619
}));
625620
}
621+
BasicQueryOpKind::Len => {
622+
return Err(TardisError {
623+
code: "500-not-supports".to_owned(),
624+
message: "search_es_item_serv len op not supports".to_owned(),
625+
});
626+
}
626627
}
627628
}
628629
}
630+
629631
if let Some(adv_query) = &search_req.adv_query {
630632
let mut adv_query_must_q = vec![];
631633
let mut adv_query_should_q = vec![];
@@ -688,7 +690,7 @@ fn gen_query_dsl(search_req: &SearchItemSearchReq) -> TardisResult<String> {
688690
}
689691
}));
690692
}
691-
BasicQueryOpKind::Like => {
693+
BasicQueryOpKind::Like | BasicQueryOpKind::LLike | BasicQueryOpKind::RLike => {
692694
group_query_q.push(json!({
693695
"match": {field: cond_info.value.clone()}
694696
}));
@@ -756,6 +758,12 @@ fn gen_query_dsl(search_req: &SearchItemSearchReq) -> TardisResult<String> {
756758
}
757759
}));
758760
}
761+
BasicQueryOpKind::Len => {
762+
return Err(TardisError {
763+
code: "500-not-supports".to_owned(),
764+
message: "search_es_item_serv len op not supports".to_owned(),
765+
})
766+
}
759767
}
760768
}
761769
match group_query.group_by_or.unwrap_or(false) {

backend/spi/spi-search/src/serv/pg/search_pg_item_serv.rs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -417,7 +417,7 @@ pub async fn search(search_req: &mut SearchItemSearchReq, funs: &TardisFunsInst,
417417
};
418418
if let Some(ext) = &search_req.query.ext {
419419
for ext_item in ext {
420-
let value = db_helper::json_to_sea_orm_value(&ext_item.value, ext_item.op == BasicQueryOpKind::Like || ext_item.op == BasicQueryOpKind::NotLike);
420+
let value = db_helper::json_to_sea_orm_value(&ext_item.value, &ext_item.op);
421421
let Some(mut value) = value else { return err_not_found(ext_item) };
422422
if ext_item.op == BasicQueryOpKind::In {
423423
let value = value.clone();
@@ -459,6 +459,13 @@ pub async fn search(search_req: &mut SearchItemSearchReq, funs: &TardisFunsInst,
459459
"(ext ->> '{}' is null or ext ->> '{}' = '' or ext ->> '{}' = '[]' )",
460460
ext_item.field, ext_item.field, ext_item.field
461461
));
462+
} else if ext_item.op == BasicQueryOpKind::Len {
463+
if let Some(first_value) = value.pop() {
464+
where_fragments.push(format!("(length(ext->>'{}')={})", ext_item.field, sql_vals.len() + 1));
465+
sql_vals.push(first_value);
466+
} else {
467+
return err_not_found(ext_item);
468+
};
462469
} else {
463470
if value.len() > 1 {
464471
return err_not_found(ext_item);
@@ -528,7 +535,7 @@ pub async fn search(search_req: &mut SearchItemSearchReq, funs: &TardisFunsInst,
528535
let mut sql_and_where = vec![];
529536
if let Some(ext) = &group_query.ext {
530537
for ext_item in ext {
531-
let value = db_helper::json_to_sea_orm_value(&ext_item.value, ext_item.op == BasicQueryOpKind::Like || ext_item.op == BasicQueryOpKind::NotLike);
538+
let value = db_helper::json_to_sea_orm_value(&ext_item.value, &ext_item.op);
532539
let Some(mut value) = value else { return err_not_found(&ext_item.clone().into()) };
533540
if ext_item.in_ext.unwrap_or(true) {
534541
if ext_item.op == BasicQueryOpKind::In {
@@ -957,7 +964,7 @@ pub async fn query_metrics(query_req: &SearchQueryMetricsReq, funs: &TardisFunsI
957964
};
958965
if let Some(ext) = &query_req.query.ext {
959966
for ext_item in ext {
960-
let value = db_helper::json_to_sea_orm_value(&ext_item.value, ext_item.op == BasicQueryOpKind::Like || ext_item.op == BasicQueryOpKind::NotLike);
967+
let value = db_helper::json_to_sea_orm_value(&ext_item.value, &ext_item.op);
961968
let Some(mut value) = value else { return err_not_found(ext_item) };
962969
if ext_item.op == BasicQueryOpKind::In {
963970
let value = value.clone();
@@ -1069,7 +1076,7 @@ pub async fn query_metrics(query_req: &SearchQueryMetricsReq, funs: &TardisFunsI
10691076
};
10701077
if let Some(ext) = &group_query.ext {
10711078
for ext_item in ext {
1072-
let value = db_helper::json_to_sea_orm_value(&ext_item.value, ext_item.op == BasicQueryOpKind::Like || ext_item.op == BasicQueryOpKind::NotLike);
1079+
let value = db_helper::json_to_sea_orm_value(&ext_item.value, &ext_item.op);
10731080
let Some(mut value) = value else { return err_not_found(ext_item) };
10741081
if ext_item.in_ext.unwrap_or(true) {
10751082
if ext_item.op == BasicQueryOpKind::In {

backend/spi/spi-stats/src/stats_enumeration.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ impl StatsDataTypeKind {
168168
Some(vec![value])
169169
}
170170
} else {
171-
db_helper::json_to_sea_orm_value(value, op == &BasicQueryOpKind::Like)
171+
db_helper::json_to_sea_orm_value(value, &op)
172172
};
173173
let Some(mut value) = value else {
174174
return Err(TardisError::internal_error("json_to_sea_orm_value result is empty", "spi-stats-inaternal-error"));
@@ -244,7 +244,7 @@ impl StatsDataTypeKind {
244244
let value = self.json_to_sea_orm_value(value, op == &BasicQueryOpKind::Like)?;
245245
Some(vec![value])
246246
} else {
247-
db_helper::json_to_sea_orm_value(value, op == &BasicQueryOpKind::Like)
247+
db_helper::json_to_sea_orm_value(value, op)
248248
};
249249

250250
let Some(mut value) = value else {

0 commit comments

Comments
 (0)