throw an error if the top left corner is found below the bottom right corner

This commit is contained in:
Tamo 2023-02-06 17:50:47 +01:00
parent 1b005f697d
commit 7a38fe624f
No known key found for this signature in database
GPG Key ID: 20CD8020AFA88D69
4 changed files with 28 additions and 11 deletions

View File

@ -540,7 +540,7 @@ async fn filter_reserved_geo_attribute_array() {
index.wait_task(1).await; index.wait_task(1).await;
let expected_response = json!({ let expected_response = json!({
"message": "`_geo` is a reserved keyword and thus can't be used as a filter expression. Use the _geoRadius(latitude, longitude, distance) built-in rule to filter on _geo field coordinates.\n1:5 _geo = Glass", "message": "`_geo` is a reserved keyword and thus can't be used as a filter expression. Use the `_geoRadius(latitude, longitude, distance)` or `_geoBoundingBox([latitude, longitude], [latitude, longitude])` built-in rules to filter on `_geo` field coordinates.\n1:5 _geo = Glass",
"code": "invalid_search_filter", "code": "invalid_search_filter",
"type": "invalid_request", "type": "invalid_request",
"link": "https://docs.meilisearch.com/errors#invalid-search-filter" "link": "https://docs.meilisearch.com/errors#invalid-search-filter"
@ -565,7 +565,7 @@ async fn filter_reserved_geo_attribute_string() {
index.wait_task(1).await; index.wait_task(1).await;
let expected_response = json!({ let expected_response = json!({
"message": "`_geo` is a reserved keyword and thus can't be used as a filter expression. Use the _geoRadius(latitude, longitude, distance) built-in rule to filter on _geo field coordinates.\n1:5 _geo = Glass", "message": "`_geo` is a reserved keyword and thus can't be used as a filter expression. Use the `_geoRadius(latitude, longitude, distance)` or `_geoBoundingBox([latitude, longitude], [latitude, longitude])` built-in rules to filter on `_geo` field coordinates.\n1:5 _geo = Glass",
"code": "invalid_search_filter", "code": "invalid_search_filter",
"type": "invalid_request", "type": "invalid_request",
"link": "https://docs.meilisearch.com/errors#invalid-search-filter" "link": "https://docs.meilisearch.com/errors#invalid-search-filter"

View File

@ -1583,20 +1583,27 @@ pub(crate) mod tests {
.unwrap(); .unwrap();
insta::assert_debug_snapshot!(search_result.candidates, @"RoaringBitmap<[4]>"); insta::assert_debug_snapshot!(search_result.candidates, @"RoaringBitmap<[4]>");
// the requests that doesn't make sense
// try to wrap around the latitude // try to wrap around the latitude
let search_result = search let error = search
.filter(Filter::from_str("_geoBoundingBox([-80, 0], [80, 0])").unwrap().unwrap()) .filter(Filter::from_str("_geoBoundingBox([-80, 0], [80, 0])").unwrap().unwrap())
.execute() .execute()
.unwrap(); .unwrap_err();
insta::assert_debug_snapshot!(search_result.candidates, @"RoaringBitmap<[]>"); insta::assert_display_snapshot!(error, @r###"
The top latitude `-80` is below the bottom latitude `80`.
32:33 _geoBoundingBox([-80, 0], [80, 0])
"###);
// the request that doesn't make sense
// send a top latitude lower than the bottow latitude // send a top latitude lower than the bottow latitude
let search_result = search let error = search
.filter(Filter::from_str("_geoBoundingBox([-10, 0], [10, 0])").unwrap().unwrap()) .filter(Filter::from_str("_geoBoundingBox([-10, 0], [10, 0])").unwrap().unwrap())
.execute() .execute()
.unwrap(); .unwrap_err();
insta::assert_debug_snapshot!(search_result.candidates, @"RoaringBitmap<[]>"); insta::assert_display_snapshot!(error, @r###"
The top latitude `-10` is below the bottom latitude `10`.
32:33 _geoBoundingBox([-10, 0], [10, 0])
"###);
} }
#[test] #[test]

View File

@ -27,6 +27,7 @@ enum FilterError<'a> {
BadGeo(&'a str), BadGeo(&'a str),
BadGeoLat(f64), BadGeoLat(f64),
BadGeoLng(f64), BadGeoLng(f64),
BadGeoBoundingBoxTopIsBelowBottom(f64, f64),
Reserved(&'a str), Reserved(&'a str),
TooDeep, TooDeep,
} }
@ -62,7 +63,8 @@ impl<'a> Display for FilterError<'a> {
"`{}` is a reserved keyword and thus can't be used as a filter expression.", "`{}` is a reserved keyword and thus can't be used as a filter expression.",
keyword keyword
), ),
Self::BadGeo(keyword) => write!(f, "`{}` is a reserved keyword and thus can't be used as a filter expression. Use the _geoRadius(latitude, longitude, distance) built-in rule to filter on _geo field coordinates.", keyword), Self::BadGeo(keyword) => write!(f, "`{}` is a reserved keyword and thus can't be used as a filter expression. Use the `_geoRadius(latitude, longitude, distance)` or `_geoBoundingBox([latitude, longitude], [latitude, longitude])` built-in rules to filter on `_geo` field coordinates.", keyword),
Self::BadGeoBoundingBoxTopIsBelowBottom(top, bottom) => write!(f, "The top latitude `{top}` is below the bottom latitude `{bottom}`."),
Self::BadGeoLat(lat) => write!(f, "Bad latitude `{}`. Latitude must be contained between -90 and 90 degrees. ", lat), Self::BadGeoLat(lat) => write!(f, "Bad latitude `{}`. Latitude must be contained between -90 and 90 degrees. ", lat),
Self::BadGeoLng(lng) => write!(f, "Bad longitude `{}`. Longitude must be contained between -180 and 180 degrees. ", lng), Self::BadGeoLng(lng) => write!(f, "Bad longitude `{}`. Longitude must be contained between -180 and 180 degrees. ", lng),
} }
@ -411,6 +413,14 @@ impl<'a> Filter<'a> {
return Err(bottom_right_point[1] return Err(bottom_right_point[1]
.as_external_error(FilterError::BadGeoLng(bottom_right[1])))?; .as_external_error(FilterError::BadGeoLng(bottom_right[1])))?;
} }
if top_left[0] < bottom_right[0] {
return Err(bottom_right_point[1].as_external_error(
FilterError::BadGeoBoundingBoxTopIsBelowBottom(
top_left[0],
bottom_right[0],
),
))?;
}
// Instead of writing a custom `GeoBoundingBox` filter we're simply going to re-use the range // Instead of writing a custom `GeoBoundingBox` filter we're simply going to re-use the range
// filter to create the following filter; // filter to create the following filter;

View File

@ -319,7 +319,7 @@ impl fmt::Debug for Search<'_> {
} }
} }
#[derive(Default)] #[derive(Default, Debug)]
pub struct SearchResult { pub struct SearchResult {
pub matching_words: MatchingWords, pub matching_words: MatchingWords,
pub candidates: RoaringBitmap, pub candidates: RoaringBitmap,