Bugzilla – Attachment 98242 Details for
Bug 24555
POC Elasticsearch - Use boolean queries instead of full text queries
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
[x]
|
Forgot Password
Login:
[x]
[patch]
Bug 24555: Replace query string with boolean query
Bug-24555-Replace-query-string-with-boolean-query.patch (text/plain), 6.41 KB, created by
Alex Arnaud
on 2020-01-31 16:04:42 UTC
(
hide
)
Description:
Bug 24555: Replace query string with boolean query
Filename:
MIME Type:
Creator:
Alex Arnaud
Created:
2020-01-31 16:04:42 UTC
Size:
6.41 KB
patch
obsolete
>From dbca822e0f442fc923491a87a11f3c64be2ed6be Mon Sep 17 00:00:00 2001 >From: Alex Arnaud <alex.arnaud@biblibre.com> >Date: Thu, 30 Jan 2020 16:13:29 +0000 >Subject: [PATCH] Bug 24555: Replace query string with boolean query > >Test plan: > Just make simple and advanced searches >--- > Koha/SearchEngine/Elasticsearch/QueryBuilder.pm | 152 ++++++++++++++++-------- > 1 file changed, 100 insertions(+), 52 deletions(-) > >diff --git a/Koha/SearchEngine/Elasticsearch/QueryBuilder.pm b/Koha/SearchEngine/Elasticsearch/QueryBuilder.pm >index c1011ec..b7619d2 100644 >--- a/Koha/SearchEngine/Elasticsearch/QueryBuilder.pm >+++ b/Koha/SearchEngine/Elasticsearch/QueryBuilder.pm >@@ -85,23 +85,7 @@ sub build_query { > $query = '*' unless defined $query; > > my $res; >- my $fields = $self->_search_fields({ >- is_opac => $options{is_opac}, >- weighted_fields => $options{weighted_fields}, >- }); >- if ($options{whole_record}) { >- push @$fields, 'marc_data_array.*'; >- } >- $res->{query} = { >- query_string => { >- query => $query, >- fuzziness => $fuzzy_enabled ? 'auto' : '0', >- default_operator => 'AND', >- fields => $fields, >- lenient => JSON::true, >- analyze_wildcard => JSON::true, >- } >- }; >+ $res->{query} = $query; > > if ( $options{sort} ) { > foreach my $sort ( @{ $options{sort} } ) { >@@ -195,23 +179,62 @@ sub build_query_compat { > }; > } > >- # We build a string query from limits and the queries. An alternative >- # would be to pass them separately into build_query and let it build >- # them into a structured ES query itself. Maybe later, though that'd be >- # more robust. >- $search_param_query_str = join( ' ', $self->_create_query_string(@search_params) ); >- $query_str = join( ' AND ', >- $search_param_query_str || (), >- $self->_join_queries( $self->_convert_index_strings(@$limits) ) || () ); >- >- # If there's no query on the left, let's remove the junk left behind >- $query_str =~ s/^ AND //; >+ > my %options; > $options{sort} = \@sort_params; > $options{is_opac} = $params->{is_opac}; > $options{weighted_fields} = $params->{weighted_fields}; > $options{whole_record} = $params->{whole_record}; >- $query = $self->build_query( $query_str, %options ); >+ >+ my $fields = $self->_search_fields({ >+ is_opac => $options{is_opac}, >+ weighted_fields => $options{weighted_fields}, >+ }); >+ if ($options{whole_record}) { >+ push @$fields, 'marc_data_array.*'; >+ } >+ >+ my $bool_query = { >+ bool => { >+ minimum_should_match => 1, >+ should => [ >+ { >+ bool => { >+ must => [] >+ } >+ } >+ ] >+ } >+ }; >+ >+ foreach my $search_param (@search_params) { >+ next if $search_param->{operand} eq '*'; >+ my $operator = $search_param->{operator} // ''; >+ my $expression = $self->_create_match_expression($search_param, \%options); >+ if (defined($expression->{multi_match})) { >+ $expression->{multi_match}->{fields} = $fields; >+ } >+ >+ if ($operator eq 'OR') { >+ push @{ $bool_query->{bool}->{should} }, { >+ bool => { >+ must => [$expression], >+ }, >+ }; >+ } else { >+ push @{ $bool_query->{bool}->{should}->[-1]->{bool}->{must} }, $expression; >+ } >+ } >+ >+ unless (@{ $bool_query->{bool}->{should}->[0]->{bool}->{must} }) { >+ $bool_query->{bool}->{should}->[0] = { match_all => {} }; >+ } >+ >+ if (@$limits) { >+ $bool_query->{bool}->{filter} = $self->_build_limit_filters($limits); >+ } >+ >+ $query = $self->build_query( $bool_query, %options ); > } > > # We roughly emulate the CGI parameters of the zebra query builder >@@ -246,6 +269,27 @@ sub build_query_compat { > ); > } > >+sub _create_match_expression { >+ my ($self, $search_param) = @_; >+ >+ my $expression = {}; >+ unless (defined($search_param->{field})) { >+ $expression->{multi_match} = { >+ query => $search_param->{operand}, >+ lenient => JSON::true >+ >+ }; >+ return $expression; >+ } >+ >+ my $field = $search_param->{field}; >+ $expression->{match} = { >+ $field => $search_param->{operand} >+ }; >+ >+ return $expression; >+} >+ > =head2 build_authorities_query > > my $query = $builder->build_authorities_query(\%search); >@@ -735,6 +779,33 @@ sub _convert_index_fields { > } @indexes; > } > >+=head2 _build_limit_filters >+ my @filters = $self->_build_limit_filters >+ >+Transform limit strings to Elasticsearch filters >+ >+=cut >+ >+sub _build_limit_filters { >+ my ( $self, $limits ) = @_; >+ my @res; >+ foreach my $s (@$limits) { >+ next if $s eq ''; >+ my ( $field, $term ) = $s =~ /^\s*([\w,-]*?):(.*)/; >+ next unless ( defined($field) && defined($term) ); >+ >+ my ($conv) = $self->_convert_index_fields($field); >+ my $facet_name = $conv->{field} . '__facet'; >+ push @res, { >+ term => { >+ $facet_name => $term >+ } >+ }; >+ } >+ >+ return \@res; >+} >+ > =head2 _convert_index_strings > > my @searches = $self->_convert_index_strings(@searches); >@@ -880,29 +951,6 @@ sub _make_phrases { > map { s/^\s*(\w*?:)(.*)$/$1"$2"/r } @parts; > } > >-=head2 _create_query_string >- >- my @query_strings = $self->_create_query_string(@queries); >- >-Given a list of hashrefs, it will turn them into a lucene-style query string. >-The hash should contain field, type (both for the indexes), operator, and >-operand. >- >-=cut >- >-sub _create_query_string { >- my ( $self, @queries ) = @_; >- >- map { >- my $otor = $_->{operator} ? $_->{operator} . ' ' : ''; >- my $field = $_->{field} ? $_->{field} . ':' : ''; >- >- my $oand = $self->_modify_string_by_type(%$_); >- $oand = "($oand)" if $field && scalar(split(/\s+/, $oand)) > 1 && (!defined $_->{type} || $_->{type} ne 'st-year'); >- "$otor($field$oand)"; >- } @queries; >-} >- > =head2 _clean_search_term > > my $term = $self->_clean_search_term($term); >-- >2.7.4
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
|
Splinter Review
Attachments on
bug 24555
:
98242
|
98243
|
98247
|
98248
|
104419
|
104422
|
105061
|
105470
|
105471
|
105472
|
105744