722: Geosearch for zero radius r=irevoire a=amab8901

# Pull Request

## Related issue
Fixes #3167 (https://github.com/meilisearch/meilisearch/issues/3167)

## What does this PR do?
- allows Geosearch with zero radius to return the specified location when the coordinates match perfectly (instead of returning nothing). See link for more details.
- new attempt on https://github.com/meilisearch/milli/pull/713

## PR checklist
Please check if your PR fulfills the following requirements:
- [ X ] Does this PR fix an existing issue, or have you listed the changes applied in the PR description (and why they are needed)?
- [ X ] Have you read the contributing guidelines?
- [ X ] Have you made sure that the title is accurate and descriptive of the changes?

Thank you so much for contributing to Meilisearch!


Co-authored-by: amab8901 <amab8901@protonmail.com>
Co-authored-by: Tamo <irevoire@protonmail.ch>
This commit is contained in:
bors[bot] 2022-12-05 19:57:08 +00:00 committed by GitHub
commit d6eacb2aac
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -420,7 +420,8 @@ impl<'a> Filter<'a> {
let result = rtree let result = rtree
.nearest_neighbor_iter(&xyz_base_point) .nearest_neighbor_iter(&xyz_base_point)
.take_while(|point| { .take_while(|point| {
distance_between_two_points(&base_point, &point.data.1) < radius distance_between_two_points(&base_point, &point.data.1)
<= radius + f64::EPSILON
}) })
.map(|point| point.data.0) .map(|point| point.data.0)
.collect(); .collect();
@ -457,10 +458,9 @@ mod tests {
#[test] #[test]
fn empty_db() { fn empty_db() {
let index = TempIndex::new(); let index = TempIndex::new();
// Set the filterable fields to be the channel. //Set the filterable fields to be the channel.
index index
.update_settings(|settings| { .update_settings(|settings| {
settings.set_searchable_fields(vec![S("PrIcE")]); // to keep the fields order
settings.set_filterable_fields(hashset! { S("PrIcE") }); settings.set_filterable_fields(hashset! { S("PrIcE") });
}) })
.unwrap(); .unwrap();
@ -626,6 +626,52 @@ mod tests {
assert_eq!(documents_ids, vec![2]); assert_eq!(documents_ids, vec![2]);
} }
#[test]
fn zero_radius() {
let index = TempIndex::new();
index
.update_settings(|settings| {
settings.set_filterable_fields(hashset! { S("_geo") });
})
.unwrap();
index
.add_documents(documents!([
{
"id": 1,
"name": "Nàpiz' Milano",
"address": "Viale Vittorio Veneto, 30, 20124, Milan, Italy",
"type": "pizza",
"rating": 9,
"_geo": {
"lat": 45.4777599,
"lng": 9.1967508
}
},
{
"id": 2,
"name": "Artico Gelateria Tradizionale",
"address": "Via Dogana, 1, 20123 Milan, Italy",
"type": "ice cream",
"rating": 10,
"_geo": {
"lat": 45.4632046,
"lng": 9.1719421
}
},
]))
.unwrap();
let rtxn = index.read_txn().unwrap();
let mut search = crate::Search::new(&rtxn, &index);
search.filter(Filter::from_str("_geoRadius(45.4777599, 9.1967508, 0)").unwrap().unwrap());
let crate::SearchResult { documents_ids, .. } = search.execute().unwrap();
assert_eq!(documents_ids, vec![0]);
}
#[test] #[test]
fn geo_radius_error() { fn geo_radius_error() {
let index = TempIndex::new(); let index = TempIndex::new();
@ -638,6 +684,7 @@ mod tests {
.unwrap(); .unwrap();
let rtxn = index.read_txn().unwrap(); let rtxn = index.read_txn().unwrap();
// georadius have a bad latitude // georadius have a bad latitude
let filter = Filter::from_str("_geoRadius(-100, 150, 10)").unwrap().unwrap(); let filter = Filter::from_str("_geoRadius(-100, 150, 10)").unwrap().unwrap();
let error = filter.evaluate(&rtxn, &index).unwrap_err(); let error = filter.evaluate(&rtxn, &index).unwrap_err();