LP1844418 Elastic Z39.50 support
authorBill Erickson <berickxx@gmail.com>
Wed, 30 Oct 2019 22:10:23 +0000 (18:10 -0400)
committerBill Erickson <berickxx@gmail.com>
Fri, 21 Feb 2020 21:20:33 +0000 (16:20 -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 159ecd7..01a0b63 100644 (file)
@@ -865,42 +865,23 @@ sub cat_search_z_style_wrapper {
     my $client = shift;
     my $authtoken = shift;
     my $args = shift;
+    my $is_staff = ($self->api_name =~ /staff$/);
 
-    my $cstore = OpenSRF::AppSession->connect('open-ils.cstore');
-
-    my $ou = $cstore->request(
-        'open-ils.cstore.direct.actor.org_unit.search',
-        { parent_ou => undef }
-    )->gather(1);
-
-    my $result = { service => 'native-evergreen-catalog', records => [] };
-    my $searchhash = { limit => $$args{limit}, offset => $$args{offset}, org_unit => $ou->id };
-
-    $$searchhash{searches}{title}{term}   = $$args{search}{title}   if $$args{search}{title};
-    $$searchhash{searches}{author}{term}  = $$args{search}{author}  if $$args{search}{author};
-    $$searchhash{searches}{subject}{term} = $$args{search}{subject} if $$args{search}{subject};
-    $$searchhash{searches}{keyword}{term} = $$args{search}{keyword} if $$args{search}{keyword};
-    $$searchhash{searches}{'identifier|isbn'}{term} = $$args{search}{isbn} if $$args{search}{isbn};
-    $$searchhash{searches}{'identifier|issn'}{term} = $$args{search}{issn} if $$args{search}{issn};
-    $$searchhash{searches}{'identifier|upc'}{term} = $$args{search}{upc} if $$args{search}{upc};
+    my $e = new_editor();
+    my $use_elastic = $e->search_config_global_flag(
+        {enabled => 't', name => 'elastic.bib_search.enabled'})->[0];
 
-    $$searchhash{searches}{keyword}{term} .= join ' ', $$searchhash{searches}{keyword}{term}, $$args{search}{tcn}       if $$args{search}{tcn};
-    $$searchhash{searches}{keyword}{term} .= join ' ', $$searchhash{searches}{keyword}{term}, $$args{search}{publisher} if $$args{search}{publisher};
-    $$searchhash{searches}{keyword}{term} .= join ' ', $$searchhash{searches}{keyword}{term}, $$args{search}{pubdate}   if $$args{search}{pubdate};
-    $$searchhash{searches}{keyword}{term} .= join ' ', $$searchhash{searches}{keyword}{term}, $$args{search}{item_type} if $$args{search}{item_type};
+    my $list = $use_elastic ?
+        zstyle_elastic($self, $args, $is_staff) : 
+        zstyle_staged($self, $args, $is_staff);
 
-    my $method = 'open-ils.search.biblio.multiclass.staged';
-    $method .= '.staff' if $self->api_name =~ /staff$/;
-
-    my ($list) = $self->method_lookup($method)->run( $searchhash );
+    my $result = {service => 'native-evergreen-catalog', records => []};
 
     if ($list->{count} > 0 and @{$list->{ids}}) {
         $result->{count} = $list->{count};
 
-        my $records = $cstore->request(
-            'open-ils.cstore.direct.biblio.record_entry.search.atomic',
-            { id => [ map { ( $_->[0] ) } @{$list->{ids}} ] }
-        )->gather(1);
+        my $records = $e->search_biblio_record_entry(
+            { id => [ map { ( $_->[0] ) } @{$list->{ids}} ] });
 
         for my $rec ( @$records ) {
             
@@ -908,16 +889,104 @@ sub cat_search_z_style_wrapper {
                         $u->start_mods_batch( $rec->marc );
                         my $mods = $u->finish_mods_batch();
 
-            push @{ $result->{records} }, { mvr => $mods, marcxml => $rec->marc, bibid => $rec->id };
-
+            push @{ $result->{records} }, 
+                { mvr => $mods, marcxml => $rec->marc, bibid => $rec->id };
         }
-
     }
 
-    $cstore->disconnect();
     return $result;
 }
 
+sub zstyle_staged {
+    my ($self, $args, $is_staff) = @_;
+
+    my @classes = qw/title author subject keyword/;
+    my @idents = qw/isbn issn upc/;
+
+    my %vals;
+    $vals{$_} = $$args{search}{$_} for @classes;
+    $vals{$_} = $$args{search}{$_} for @idents;
+
+    # Append these to the keyword search (backwards compat).
+    # TODO: these should search specific indexes instead of keyword.
+    for my $kw (qw/tcn publisher pubdate item_type/) {
+        $vals{keyword} .= join(' ', $vals{keyword}, $$args{search}{$kw}) 
+            if $$args{search}{$kw};
+    }
+
+    my $searchhash = {
+        limit => $$args{limit}, 
+        offset => $$args{offset}, 
+        org_unit => $U->get_org_tree->id
+    };
+
+    for my $class (@classes) {
+        $$searchhash{searches}{$class}{term} = 
+            $vals{$class} if $vals{$class};
+    }
+
+    for my $ident (@idents) {
+        $$searchhash{searches}{"identifier|$ident"}{term} =     
+            $vals{$ident} if $vals{$ident};
+    }
+
+    my $method = 'open-ils.search.biblio.multiclass.staged';
+    $method .= '.staff' if $is_staff;
+
+    my ($list) = $self->method_lookup($method)->run($searchhash);
+    return $list;
+}
+
+sub zstyle_elastic {
+    my ($self, $args, $is_staff) = @_;
+
+    my @classes = qw/title author subject keyword/;
+    my @idents = qw/isbn issn upc tcn publisher pubdate/;
+
+    my %vals;
+    $vals{$_} = $$args{search}{$_} for @classes;
+    $vals{$_} = $$args{search}{$_} for @idents;
+
+    my $search = {
+        from => $$args{offset},
+        size => $$args{limit},
+        sort => [{_score => 'desc'}],
+        query => {bool => {must => []}}
+    };
+
+    my $ops = {disable_facets => 1};
+
+    # use a filter for item_type.
+    my $itype = $$args{item_type};
+    $search->{filter} = [{term => {item_type => $itype}}] if $itype;
+
+    for my $class (grep {$vals{$_}} @classes) {
+        push(@{$search->{query}->{bool}->{must}}, {
+            multi_match => {
+                type => 'best_fields', 
+                fields => "$class|*text*", 
+                query => $vals{$class}
+            }
+        });
+    }
+
+    for my $ident (grep {$vals{$_}} @idents) {
+        push(@{$search->{query}->{bool}->{must}}, 
+            {term => {"identifier|$ident" => $vals{$ident}}});
+    }
+
+    # avoid bogus searches
+    return [] unless (@{$search->{query}->{bool}->{must}});
+
+    my $method = 'open-ils.search.elastic.bib_search' ;
+    $method .= '.staff' if $is_staff;
+
+    my ($list) = $self->method_lookup($method)->run($search, $ops);
+
+    return $list;
+}
+
+
 # ----------------------------------------------------------------------------
 # These are the main OPAC search methods
 # ----------------------------------------------------------------------------
index dac1c5b..3fde569 100644 (file)
@@ -141,6 +141,8 @@ __PACKAGE__->register_method(
 
                         available - Ensure that at least one item is 
                             considered available within the search scope.
+
+                        disable_facets - If true, disable ES aggregations
                 /
             }
         ],
@@ -268,7 +270,7 @@ sub compile_elastic_query {
     add_elastic_holdings_filter($elastic, $staff, 
         $options->{search_org}, $options->{search_depth}, $options->{available});
 
-    add_elastic_facet_aggregations($elastic);
+    add_elastic_facet_aggregations($elastic) unless $options->{disable_facets};
 
     $elastic->{sort} = ['_score'] unless @{$elastic->{sort} || []};