From c42fe526999bf439fe80c5bc068976fb9b770af2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tadeusz=20=E2=80=9Etadzik=E2=80=9D=20So=C5=9Bnierz?= Date: Wed, 31 Jul 2024 16:15:58 +0200 Subject: [PATCH] Allow bounding-box searches in geolocation queries --- .../Elasticsearch/QueryBuilder.pm | 34 ++++++++++++++----- .../SearchEngine/Elasticsearch/QueryBuilder.t | 32 +++++++++++++++++ 2 files changed, 58 insertions(+), 8 deletions(-) diff --git a/Koha/SearchEngine/Elasticsearch/QueryBuilder.pm b/Koha/SearchEngine/Elasticsearch/QueryBuilder.pm index dea84c83a2..945ca50ccc 100644 --- a/Koha/SearchEngine/Elasticsearch/QueryBuilder.pm +++ b/Koha/SearchEngine/Elasticsearch/QueryBuilder.pm @@ -1418,14 +1418,32 @@ sub _rebuild_to_es_advanced_query { my %filter; for my $advanced_query (@$es_advanced_searches) { if ( $advanced_query->{field} eq 'geolocation' ) { - my ( $lat, $lon, $distance ) = map { $_ =~ /:(.*)\*/ } split( '\s+', $advanced_query->{operand} ); - $filter{geo_distance} = { - distance => $distance, - geolocation => { - lat => $lat, - lon => $lon, - } - }; + my %args = map { split ':' } map { s/\*$//r } split /\s+/, $advanced_query->{operand}; + if ($args{lat} and $args{lng} and $args{distance}) { + $filter{geo_distance} = { + distance => $args{distance}, + geolocation => { + lat => $args{lat}, + lon => $args{lng}, + } + }; + } elsif ($args{boundingbox}) { + my ($top_left_lat, $top_left_lon, $bottom_right_lat, $bottom_right_lon) = split ',', $args{boundingbox}; + $filter{geo_bounding_box} = { + 'geolocation' => { + 'top_left' => { + 'lat' => $top_left_lat, + 'lon' => $top_left_lon, + }, + 'bottom_right' => { + 'lat' => $bottom_right_lat, + 'lon' => $bottom_right_lon, + } + }, + }; + } else { + warn "Unrecognized parameter set for geolocation queries: " . join(', ', keys %args); + } } else { warn "unknown advanced ElasticSearch query: " . join( ', ', %$advanced_query ); } diff --git a/t/Koha/SearchEngine/Elasticsearch/QueryBuilder.t b/t/Koha/SearchEngine/Elasticsearch/QueryBuilder.t index b6b670d7d5..eef358a0f7 100755 --- a/t/Koha/SearchEngine/Elasticsearch/QueryBuilder.t +++ b/t/Koha/SearchEngine/Elasticsearch/QueryBuilder.t @@ -369,5 +369,37 @@ subtest '_create_query_string' => sub { }; +subtest 'geolocation queries' => sub { + my $qb = Koha::SearchEngine::Elasticsearch::QueryBuilder->new({ + index => $Koha::SearchEngine::Elasticsearch::BIBLIOS_INDEX, + }); + + $qb->_create_query_string({ + 'field' => 'geolocation', + 'operand' => 'lat:48.25* lng:16.35* distance:100km*' + }); + my $query = $qb->build_query(); + is_deeply $query->{query}{bool}{filter}, { + geo_distance => { + distance => '100km', + geolocation => { lat => 48.25, lon => 16.35 }, + } + }, 'should be able to create "distance from a point" queries'; + + $qb->_create_query_string({ + 'field' => 'geolocation', + 'operand' => 'boundingbox:1,2,3,4*' + }); + $query = $qb->build_query(); + is_deeply $query->{query}{bool}{filter}, { + geo_bounding_box => { + geolocation => { + top_left => { lat => 1, lon => 2 }, + bottom_right => { lat => 3, lon => 4 }, + }, + } + }, 'should be able to create "within a bounding box" queries'; +}; + 1; -- 2.45.2