$user_offset = ($user_offset >= 0) ? $user_offset : 0;
$user_limit = ($user_limit >= 0) ? $user_limit : 10;
- # TODO TODO check settings/db to see if elasticsearch is
- # enabled for bib-search.
- if (1) {
+ # TODO: cache this. Real-time lookups are better for testing, though.
+ my $use_elastic = new_editor()->search_elastic_index({
+ active => 't', code => 'bib-search'})->[0];
+
+ if ($use_elastic) {
return OpenILS::Application::Search::Elastic->bib_search(
- $search_hash->{query}, $user_offset, $user_limit);
+ $search_hash->{query}, ($method =~ /staff/ ? 1 : 0),
+ $user_offset, $user_limit
+ );
}
# we're grabbing results on a per-superpage basis, which means the
use OpenILS::Utils::CStoreEditor q/:funcs/;
use OpenILS::Elastic::BibSearch;
use List::Util qw/min/;
+use Digest::MD5 qw(md5_hex);
use OpenILS::Application::AppUtils;
my $U = "OpenILS::Application::AppUtils";
# Translate search results into a structure consistent with a bib search
# API response.
sub bib_search {
- my ($class, $query, $offset, $limit) = @_;
+ my ($class, $query, $staff, $offset, $limit) = @_;
$bib_search_fields =
new_editor()->retrieve_all_elastic_bib_field()
unless $bib_search_fields;
- my $elastic_query = translate_elastic_query($query, $offset, $limit);
+ my ($elastic_query, $cache_key) =
+ translate_elastic_query($query, $staff, $offset, $limit);
$logger->info("ES sending query to elasticsearch: ".
OpenSRF::Utils::JSON->perl2JSON($elastic_query));
return {count => 0} unless $results;
+ format_facets($results->{aggregations});
+
return {
count => $results->{hits}->{total},
ids => [
map { [$_->{_id}, undef, $_->{_score}] }
grep {defined $_} @{$results->{hits}->{hits}}
- ]
+ ],
+ facets => $results->{aggregations},
+ # Note at time of writing no search caching is used for
+ # Elasticsearch, but providing cache keys allows the caller to
+ # know if this search matches another search.
+ cache_key => $cache_key,
+ facet_key => $cache_key.'_facets'
};
}
+
+sub format_facets {
+ my $aggregations = shift;
+ my $facets = {}; # cmf.id => {"Facet Value" => count}
+
+ for my $fname (keys %$aggregations) {
+
+ my ($name, $field_class) = split('|', $fname);
+ my ($bib_field) = grep {
+ $_->{name} eq $name && $_->{search_group} eq $field_class
+ } @$bib_search_fields;
+
+ my $hash = $facets->{$bib_field->metabib_field} = {};
+
+ my $values = $aggregations->{$fname}->{buckets};
+ for my $bucket (@$values) {
+ $hash->{$bucket->{key}} = $bucket->{doc_count};
+ }
+ }
+
+ return $facets;
+}
+
sub translate_elastic_query {
- my ($query, $offset, $limit) = @_;
+ my ($query, $staff, $offset, $limit) = @_;
# Scrub functions and tags from the bare query so they may
# be translated to elastic equivalents. We only want the
}
}
+ my $cache_seed = "$query $staff $available ";
+ # TODO: confirm matches @funcs above where needed
+ for my $key (qw/site depth item_lang/) {
+ $cache_seed .= " $key=" . $calls{$key} if defined $calls{$key};
+ }
+
+ my $cache_key = md5_hex($cache_seed);
+ $logger->info("ES cache seed = $cache_seed | $cache_key");
+
my $elastic_query = {
_source => ['id'], # Fetch bib ID only
size => $limit,
add_elastic_facets($elastic_query);
- return $elastic_query;
+ return ($elastic_query, $cache_key);
}
sub add_elastic_facets {
$depth = defined $depth ? min($depth, $type->depth) : $type->depth;
+ # TODO: if $staff is false, add a holdings filter for
+ # opac_visble / location.opac_visible / status.opac_visible
+
if ($depth > 0) {
if (!$org_data_cache{ancestors_at}{$shortname}) {