Skip to content

Commit e08eb9f

Browse files
authored
Bugfix sort order query string in elastic search api. (#5490)
The sort order was parsed using the generated from_str_name method. The spec of this method probably changed at one point, and we ended up requiring sort order to be uppercase. This PR changes the behavior to follow what we do when we parse a json string, and adds unit tests. Closes #5491
1 parent 4c1e228 commit e08eb9f

File tree

2 files changed

+68
-3
lines changed

2 files changed

+68
-3
lines changed

quickwit/quickwit-serve/src/elasticsearch_api/model/search_query_params.rs

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ use std::fmt;
2121
use std::str::FromStr;
2222
use std::time::Duration;
2323

24-
use quickwit_proto::search::SortOrder;
2524
use quickwit_query::BooleanOperand;
2625
use quickwit_search::SearchError;
2726
use serde::{Deserialize, Serialize};
@@ -232,10 +231,16 @@ pub struct DeleteQueryParams {
232231
pub timeout: Option<String>,
233232
}
234233

234+
/// Parses a string as if it was a json value string.
235+
fn parse_str_like_json<T: serde::de::DeserializeOwned>(s: &str) -> Option<T> {
236+
let json_value = serde_json::Value::String(s.to_string());
237+
serde_json::from_value::<T>(json_value).ok()
238+
}
239+
235240
// Parse a single sort field parameter from ES sort query string parameter.
236241
fn parse_sort_field_str(sort_field_str: &str) -> Result<SortField, SearchError> {
237242
if let Some((field, order_str)) = sort_field_str.split_once(':') {
238-
let order = SortOrder::from_str_name(order_str).ok_or_else(|| {
243+
let order = parse_str_like_json(order_str).ok_or_else(|| {
239244
SearchError::InvalidArgument(format!(
240245
"invalid sort order `{}`. expected `asc` or `desc`",
241246
field
@@ -375,3 +380,49 @@ impl fmt::Display for SuggestMode {
375380
}
376381
}
377382
}
383+
384+
#[cfg(test)]
385+
mod tests {
386+
387+
use quickwit_proto::search::SortOrder;
388+
389+
use super::*;
390+
391+
#[derive(Deserialize, PartialEq, Eq, Debug)]
392+
#[serde(rename_all = "snake_case")]
393+
enum TestEnum {
394+
FirstItem,
395+
SecondItem,
396+
}
397+
398+
#[test]
399+
fn test_parse_str_like_json() {
400+
assert_eq!(
401+
parse_str_like_json::<TestEnum>("first_item").unwrap(),
402+
TestEnum::FirstItem
403+
);
404+
assert!(parse_str_like_json::<TestEnum>("FirstItem").is_none());
405+
}
406+
407+
#[test]
408+
fn test_sort_order_qs() {
409+
let sort_order_qs = parse_sort_field_str("timestamp:desc").unwrap();
410+
assert_eq!(
411+
sort_order_qs,
412+
SortField {
413+
field: "timestamp".to_string(),
414+
order: SortOrder::Desc,
415+
date_format: None
416+
}
417+
);
418+
let sort_order_qs = parse_sort_field_str("timestamp:asc").unwrap();
419+
assert_eq!(
420+
sort_order_qs,
421+
SortField {
422+
field: "timestamp".to_string(),
423+
order: SortOrder::Asc,
424+
date_format: None
425+
}
426+
);
427+
}
428+
}

quickwit/rest-api-tests/scenarii/es_compatibility/0008-sort_by.yaml

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,21 @@ expected:
1515
actor:
1616
id: 10791502
1717
---
18+
# Checking that passing the sort params as a query string works.
19+
params:
20+
sort: "actor.id:desc"
21+
q: "*"
22+
size: 1
23+
expected:
24+
hits:
25+
total:
26+
value: 100
27+
relation: eq
28+
hits:
29+
- _source:
30+
actor:
31+
id: 10791502
32+
---
1833
json:
1934
size: 1
2035
query:
@@ -113,4 +128,3 @@ expected:
113128
- _source:
114129
actor:
115130
id: 1762355
116-

0 commit comments

Comments
 (0)