From: Bill Erickson Date: Wed, 24 Oct 2018 19:20:53 +0000 (-0400) Subject: bib-search indexing; search api wip X-Git-Url: https://old-git.evergreen-ils.org/?a=commitdiff_plain;h=b0eb6a795175c277fd2f4c066019eb1c48e71597;p=working%2FEvergreen.git bib-search indexing; search api wip Signed-off-by: Bill Erickson --- diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Application/Search/Biblio.pm b/Open-ILS/src/perlmods/lib/OpenILS/Application/Search/Biblio.pm index 5f3846a0bd..46b79a3308 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/Application/Search/Biblio.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/Application/Search/Biblio.pm @@ -1314,17 +1314,25 @@ sub staged_search { sub elastic_search { my ($query, $offset, $limit) = @_; - # TODO visibility limits on holdings summaries - my ($site) = ($query =~ /site\(([^\)]+)\)/); - $query =~ s/site\(([^\)]+)\)//g; + my ($available) = ($query =~ s/(\#available)//g); + my ($descending) = ($query =~ s/(\#descending)//g); + + my @funcs = qw/site depth sort item_lang/; # todo add others + my %calls; + + for my $func (@funcs) { + my ($val) = ($query =~ /$func\(([^\)]+)\)/); + if (defined $val) { + # scrub from query string + $query =~ s/$func\(([^\)]+)\)//g; + $calls{$func} = $val; + } + } + my $elastic_query = { - _source => ['id'] , # return only the ID field -# sort => [ -# {'title.raw' => 'asc'}, -# {'author.raw' => 'asc'}, -# '_score' -# ], + # Fetch only the bib ID field from each source document + _source => ['id'], size => $limit, from => $offset, query => { @@ -1339,6 +1347,68 @@ sub elastic_search { } }; + # No need to filter on holdings lib when searching globally + # (i.e. depth = 0) + if ($calls{site}) { + + my $types = $U->get_org_types; + my $org = $U->find_org_by_shortname($U->get_org_tree, $calls{site}); + my ($type) = grep {$_->id == $org->ou_type} @$types; + my $depth = $calls{depth} || $type->depth; + + # No holdings-level circ lib filter needed when searching globally + if ($depth > 0) { + + # TODO + # this makes a cstore call, but could easily come from cache. + my $org_ids = $U->get_org_descendants($org->id, $depth); + + # Add a boolean OR-filter on holdings circ lib and optionally + # add a boolean AND-filter on copy status for availability + # checking. + $elastic_query->{query}->{bool}->{filter} = { + nested => { + path => 'holdings', + query => {bool => {should => []}} + } + }; + + my $should = + $elastic_query->{query}{bool}{filter}{nested}{query}{bool}{should}; + + for my $org_id (@$org_ids) { + + # Ensure at least one copy exists at the selected org unit + my $and = { + bool => { + must => [ + {term => {'holdings.circ_lib' => $org_id}} + ] + } + }; + + # When limiting to available, ensure at least one of the + # above copies is in status 0 or 7. + # TODO: consult config.copy_status.is_available + push( + @{$and->{bool}{must}}, + {terms => {'holdings.status' => [0, 7]}} + ) if $available; + + push(@$should, $and); + } + } + } + + if ($calls{sort}) { + my $key = 'title.raw' if ($calls{sort} =~ /title/); + $key = 'author.raw' if ($calls{sort} =~ /author/); + $key = 'pub_date' if ($calls{sort} =~ /pubdate/); + if ($key) { + $elastic_query->{sort} = [{$key => $descending ? 'desc' : 'asc'}]; + } + } + my $es = OpenILS::Elastic::BibSearch->new('main'); $es->connect; my $results = $es->search($elastic_query); diff --git a/Open-ILS/src/perlmods/lib/OpenILS/Elastic.pm b/Open-ILS/src/perlmods/lib/OpenILS/Elastic.pm index 9892a6db8e..9f75ee6a35 100644 --- a/Open-ILS/src/perlmods/lib/OpenILS/Elastic.pm +++ b/Open-ILS/src/perlmods/lib/OpenILS/Elastic.pm @@ -202,8 +202,8 @@ sub search { } $logger->info( - sprintf("ES search found %d results in %f seconds.", - $result->{hits}->{total}, substr($duration, 0, 6) + sprintf("ES search found %d results in %0.3f seconds.", + $result->{hits}->{total}, $duration ) );