bib search api wip
authorBill Erickson <berickxx@gmail.com>
Mon, 29 Oct 2018 22:01:38 +0000 (18:01 -0400)
committerBill Erickson <berickxx@gmail.com>
Fri, 8 Feb 2019 19:30:35 +0000 (14:30 -0500)
Signed-off-by: Bill Erickson <berickxx@gmail.com>
Open-ILS/src/perlmods/lib/OpenILS/Application/Search/Biblio.pm
Open-ILS/src/perlmods/lib/OpenILS/Application/Search/Elastic.pm

index 9c7bc6a..446135b 100644 (file)
@@ -1157,11 +1157,15 @@ sub staged_search {
     $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 
index 29fb883..e82e50a 100644 (file)
@@ -22,6 +22,7 @@ use OpenSRF::Utils::SettingsClient;
 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";
@@ -36,13 +37,14 @@ my %org_data_cache = (by_shortname => {}, ancestors_at => {});
 # 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));
@@ -57,17 +59,48 @@ sub bib_search {
 
     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 
@@ -91,6 +124,15 @@ sub translate_elastic_query {
         }
     }
 
+    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,
@@ -118,7 +160,7 @@ sub translate_elastic_query {
 
     add_elastic_facets($elastic_query);
         
-    return $elastic_query;
+    return ($elastic_query, $cache_key);
 }
 
 sub add_elastic_facets {
@@ -161,6 +203,9 @@ sub add_elastic_holdings_filter {
 
     $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}) {