Lines 102-111
sub build_query {
Link Here
|
102 |
if $d && ( $d ne 'asc' && $d ne 'desc' ); |
102 |
if $d && ( $d ne 'asc' && $d ne 'desc' ); |
103 |
$d = 'asc' unless $d; |
103 |
$d = 'asc' unless $d; |
104 |
|
104 |
|
105 |
# TODO account for fields that don't have a 'phrase' type |
|
|
106 |
|
107 |
$f = $self->_sort_field($f); |
105 |
$f = $self->_sort_field($f); |
108 |
push @{ $res->{sort} }, { "$f.phrase" => { order => $d } }; |
106 |
push @{ $res->{sort} }, { $f => { order => $d } }; |
109 |
} |
107 |
} |
110 |
} |
108 |
} |
111 |
|
109 |
|
Lines 171-177
sub build_browse_query {
Link Here
|
171 |
} |
169 |
} |
172 |
} |
170 |
} |
173 |
}, |
171 |
}, |
174 |
sort => [ { "$sort.phrase" => { order => "asc" } } ], |
172 |
sort => [ { $sort => { order => "asc" } } ], |
175 |
}; |
173 |
}; |
176 |
} |
174 |
} |
177 |
|
175 |
|
Lines 294-300
sub build_authorities_query {
Link Here
|
294 |
foreach my $s ( @{ $search->{searches} } ) { |
292 |
foreach my $s ( @{ $search->{searches} } ) { |
295 |
my ( $wh, $op, $val ) = @{$s}{qw(where operator value)}; |
293 |
my ( $wh, $op, $val ) = @{$s}{qw(where operator value)}; |
296 |
$wh = '_all' if $wh eq ''; |
294 |
$wh = '_all' if $wh eq ''; |
297 |
if ( $op eq 'is' || $op eq '=' ) { |
295 |
if ( $op eq 'is' || $op eq '=' || $op eq 'exact' ) { |
298 |
|
296 |
|
299 |
# look for something that matches completely |
297 |
# look for something that matches completely |
300 |
# note, '=' is about numerical vals. May need special handling. |
298 |
# note, '=' is about numerical vals. May need special handling. |
Lines 302-313
sub build_authorities_query {
Link Here
|
302 |
# matches. Also, we lowercase our search because the ES |
300 |
# matches. Also, we lowercase our search because the ES |
303 |
# index lowercases its values, and term searches don't get the |
301 |
# index lowercases its values, and term searches don't get the |
304 |
# search analyzer applied to them. |
302 |
# search analyzer applied to them. |
305 |
push @filter_parts, { term => { "$wh.phrase" => lc $val } }; |
303 |
push @query_parts, { match_phrase => { "$wh.phrase" => lc $val } }; |
306 |
} |
|
|
307 |
elsif ( $op eq 'exact' ) { |
308 |
|
309 |
# left and right truncation, otherwise an exact phrase |
310 |
push @query_parts, { match_phrase => { $wh => $val } }; |
311 |
} |
304 |
} |
312 |
elsif ( $op eq 'start' ) { |
305 |
elsif ( $op eq 'start' ) { |
313 |
|
306 |
|
Lines 316-337
sub build_authorities_query {
Link Here
|
316 |
} |
309 |
} |
317 |
else { |
310 |
else { |
318 |
# regular wordlist stuff |
311 |
# regular wordlist stuff |
319 |
push @query_parts, { match => { $wh => $val } }; |
312 |
push @query_parts, { match => { $wh => { query => $val, operator => 'AND' } } }; |
320 |
} |
313 |
} |
321 |
} |
314 |
} |
322 |
|
315 |
|
|
|
316 |
# Add authtype if specified |
317 |
if (defined $search->{authtypecode} && $search->{authtypecode}) { |
318 |
push @query_parts, { match => { authtype => $search->{authtypecode} } }; |
319 |
} |
320 |
|
323 |
# Merge the query and filter parts appropriately |
321 |
# Merge the query and filter parts appropriately |
324 |
# 'should' behaves like 'or', if we want 'and', use 'must' |
322 |
# 'should' behaves like 'or', if we want 'and', use 'must' |
325 |
my $query_part = { bool => { should => \@query_parts } }; |
323 |
my $query_part = { bool => { must => \@query_parts } }; |
326 |
my $filter_part = { bool => { should => \@filter_parts } }; |
324 |
my $filter_part = { bool => { must => \@filter_parts } }; |
327 |
|
325 |
|
328 |
# We need to add '.phrase' to all the sort headings otherwise it'll sort |
|
|
329 |
# based on the tokenised form. |
330 |
my %s; |
326 |
my %s; |
331 |
if ( exists $search->{sort} ) { |
327 |
if ( exists $search->{sort} ) { |
332 |
foreach my $k ( keys %{ $search->{sort} } ) { |
328 |
foreach my $k ( keys %{ $search->{sort} } ) { |
333 |
my $f = $self->_sort_field($k); |
329 |
my $f = $self->_sort_field($k); |
334 |
$s{"$f.phrase"} = $search->{sort}{$k}; |
330 |
$s{$f} = $search->{sort}{$k}; |
335 |
} |
331 |
} |
336 |
$search->{sort} = \%s; |
332 |
$search->{sort} = \%s; |
337 |
} |
333 |
} |
Lines 383-391
Also ignored.
Link Here
|
383 |
|
379 |
|
384 |
=item operator |
380 |
=item operator |
385 |
|
381 |
|
386 |
What form of search to do. Options are: is (phrase, no trunction, whole field |
382 |
What form of search to do. Options are: is (phrase, no truncation, whole field |
387 |
must match), = (number exact match), exact (phrase, but with left and right |
383 |
must match), = (number exact match), exact (phrase, no truncation, whole field |
388 |
truncation). If left blank, then word list, right truncted, anywhere is used. |
384 |
must match). If left blank, then word list, right truncated, anywhere is used. |
389 |
|
385 |
|
390 |
=item value |
386 |
=item value |
391 |
|
387 |
|
Lines 417-423
our $koha_to_index_name = {
Link Here
|
417 |
'match-heading' => 'Match-heading', |
413 |
'match-heading' => 'Match-heading', |
418 |
'see-from' => 'Match-heading-see-from', |
414 |
'see-from' => 'Match-heading-see-from', |
419 |
thesaurus => 'Subject-heading-thesaurus', |
415 |
thesaurus => 'Subject-heading-thesaurus', |
420 |
all => '' |
416 |
any => '', |
|
|
417 |
all => '' |
421 |
}; |
418 |
}; |
422 |
|
419 |
|
423 |
sub build_authorities_query_compat { |
420 |
sub build_authorities_query_compat { |
Lines 435-452
sub build_authorities_query_compat {
Link Here
|
435 |
unless exists $koha_to_index_name->{$m}; |
432 |
unless exists $koha_to_index_name->{$m}; |
436 |
} |
433 |
} |
437 |
for ( my $i = 0 ; $i < @$value ; $i++ ) { |
434 |
for ( my $i = 0 ; $i < @$value ; $i++ ) { |
438 |
push @searches, |
435 |
if (defined $value->[$i]) { |
439 |
{ |
436 |
my $escaped_value = $value->[$i]; |
440 |
where => $koha_to_index_name->{$marclist->[$i]}, |
437 |
$escaped_value =~ s/(["()\\])/\\$1/g; |
441 |
operator => $operator->[$i], |
438 |
push @searches, |
442 |
value => $value->[$i], |
439 |
{ |
443 |
}; |
440 |
where => $koha_to_index_name->{$marclist->[$i]}, |
|
|
441 |
operator => $operator->[$i], |
442 |
value => $escaped_value, |
443 |
}; |
444 |
} |
444 |
} |
445 |
} |
445 |
|
446 |
|
446 |
my %sort; |
447 |
my %sort; |
447 |
my $sort_field = |
448 |
my $sort_field = |
448 |
( $orderby =~ /^Heading/ ) ? 'Heading' |
449 |
( $orderby =~ /^Heading/ ) ? 'Heading' |
449 |
: ( $orderby =~ /^Auth/ ) ? 'Local-Number' |
450 |
: ( $orderby =~ /^Auth/ ) ? 'Local-number' |
450 |
: undef; |
451 |
: undef; |
451 |
if ($sort_field) { |
452 |
if ($sort_field) { |
452 |
my $sort_order = ( $orderby =~ /Asc$/ ) ? 'asc' : 'desc'; |
453 |
my $sort_order = ( $orderby =~ /Asc$/ ) ? 'asc' : 'desc'; |
Lines 778-785
the end. Maybe it'll be something else in the future, who knows?
Link Here
|
778 |
|
779 |
|
779 |
sub _sort_field { |
780 |
sub _sort_field { |
780 |
my ($self, $f) = @_; |
781 |
my ($self, $f) = @_; |
|
|
782 |
|
783 |
my $mappings = $self->get_elasticsearch_mappings(); |
784 |
my $textField = defined $mappings->{data}{properties}{$f}{type} && $mappings->{data}{properties}{$f}{type} eq 'text'; |
781 |
if ($self->sort_fields()->{$f}) { |
785 |
if ($self->sort_fields()->{$f}) { |
782 |
$f .= '__sort'; |
786 |
$f .= '__sort'; |
|
|
787 |
# We need to add '.phrase' to text fields, otherwise it'll sort |
788 |
# based on the tokenised form. |
789 |
$f .= '.phrase' if $textField; |
790 |
} else { |
791 |
# We need to add '.raw' to text fields without a sort field, |
792 |
# otherwise it'll sort based on the tokenised form. |
793 |
$f .= '.raw' if $textField; |
783 |
} |
794 |
} |
784 |
return $f; |
795 |
return $f; |
785 |
} |
796 |
} |