From 34e18bc16619b1bb7b27498e965b0b7a2af66f28 Mon Sep 17 00:00:00 2001 From: Julian Maurice Date: Tue, 10 Nov 2020 15:22:21 +0100 Subject: [PATCH] Bug 25030: Implement IncludeSeeFromInSearches with Elasticsearch MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Test plan: 1. Create an authority with at least a 1XX$a and a 4XX$a, for instance: 100 $a Foo 400 $a Bar 2. Create a biblio and add a link to this authority using the cataloguing plugin 3. Disable syspref IncludeSeeFromInSearches 4. Reindex the biblio. You should be able to find it when searching 'Foo' but not when searching 'Bar' 5. Enable syspref IncludeSeeFromInSearches 6. Reindex the biblio. You should be able to find it when searching 'Foo' and also when searching 'Bar' without the patch, 'Bar' doesn't yeld results. With it, it does. 7. prove t/db_dependent/Koha/SearchEngine/Elasticsearch.t Signed-off-by: Séverine QUEUNE Signed-off-by: Lucy Vaux-Harvey --- Koha/Filter/MARC/EmbedSeeFromHeadings.pm | 20 +++-- Koha/SearchEngine/Elasticsearch.pm | 49 ++++++++++++ .../Koha/SearchEngine/Elasticsearch.t | 78 ++++++++++++++++++- 3 files changed, 140 insertions(+), 7 deletions(-) diff --git a/Koha/Filter/MARC/EmbedSeeFromHeadings.pm b/Koha/Filter/MARC/EmbedSeeFromHeadings.pm index b00a9a2d6e..6ff96b8b35 100644 --- a/Koha/Filter/MARC/EmbedSeeFromHeadings.pm +++ b/Koha/Filter/MARC/EmbedSeeFromHeadings.pm @@ -58,22 +58,31 @@ sub filter { if (ref $record eq 'ARRAY') { my @recarray; foreach my $thisrec (@$record) { - push @recarray, _processrecord($thisrec); + push @recarray, $self->_processrecord($thisrec); } $newrecord = \@recarray; } elsif (ref $record eq 'MARC::Record') { - $newrecord = _processrecord($record); + $newrecord = $self->_processrecord($record); } return $newrecord; } sub _processrecord { - my $record = shift; + my ($self, $record) = @_; + + $record->append_fields($self->fields($record)); + + return $record; +} + +sub fields { + my ($self, $record) = @_; my ($item_tag) = GetMarcFromKohaField( "items.itemnumber" ); $item_tag ||= ''; + my @newfields; foreach my $field ( $record->fields() ) { next if $field->is_control_field(); next if $field->tag() eq $item_tag; @@ -85,7 +94,6 @@ sub _processrecord { next unless $authority; my $auth_marc = $authority->record; my @seefrom = $auth_marc->field('4..'); - my @newfields; foreach my $authfield (@seefrom) { my $tag = substr($field->tag(), 0, 1) . substr($authfield->tag(), 1, 2); next if MARC::Field->is_controlfield_tag($tag); @@ -100,9 +108,9 @@ sub _processrecord { $newfield->delete_subfield( code => '9' ); push @newfields, $newfield if (scalar($newfield->subfields()) > 0); } - $record->append_fields(@newfields); } - return $record; + + return @newfields; } 1; diff --git a/Koha/SearchEngine/Elasticsearch.pm b/Koha/SearchEngine/Elasticsearch.pm index 826bb06b26..f4a2f82713 100644 --- a/Koha/SearchEngine/Elasticsearch.pm +++ b/Koha/SearchEngine/Elasticsearch.pm @@ -24,6 +24,7 @@ use C4::Context; use Koha::Database; use Koha::Exceptions::Config; use Koha::Exceptions::Elasticsearch; +use Koha::Filter::MARC::EmbedSeeFromHeadings; use Koha::SearchFields; use Koha::SearchMarcMaps; use Koha::Caches; @@ -639,6 +640,54 @@ sub marc_records_to_documents { } } } + + if (C4::Context->preference('IncludeSeeFromInSearches') and $self->index eq 'biblios') { + foreach my $field (Koha::Filter::MARC::EmbedSeeFromHeadings->new->fields($record)) { + my $data_field_rules = $data_fields_rules->{$field->tag()}; + if ($data_field_rules) { + my $subfields_mappings = $data_field_rules->{subfields}; + my $wildcard_mappings = $subfields_mappings->{'*'}; + foreach my $subfield ($field->subfields()) { + my ($code, $data) = @{$subfield}; + my @mappings; + push @mappings, @{ $subfields_mappings->{$code} } if $subfields_mappings->{$code}; + push @mappings, @$wildcard_mappings if $wildcard_mappings; + # Do not include "see from" into these kind of fields + @mappings = grep { $_->[0] !~ /__(sort|facet|suggestion)$/ } @mappings; + if (@mappings) { + $self->_process_mappings(\@mappings, $data, $record_document, { + data_source => 'subfield', + code => $code, + field => $field + } + ); + } + } + + my $subfields_join_mappings = $data_field_rules->{subfields_join}; + if ($subfields_join_mappings) { + foreach my $subfields_group (keys %{$subfields_join_mappings}) { + my $data_field = $field->clone; + # remove empty subfields, otherwise they are printed as a space + $data_field->delete_subfield(match => qr/^$/); + my $data = $data_field->as_string( $subfields_group ); + if ($data) { + my @mappings = @{ $subfields_join_mappings->{$subfields_group} }; + # Do not include "see from" into these kind of fields + @mappings = grep { $_->[0] !~ /__(sort|facet|suggestion)$/ } @mappings; + $self->_process_mappings(\@mappings, $data, $record_document, { + data_source => 'subfields_group', + codes => $subfields_group, + field => $field + } + ); + } + } + } + } + } + } + foreach my $field (keys %{$rules->{defaults}}) { unless (defined $record_document->{$field}) { $record_document->{$field} = $rules->{defaults}->{$field}; diff --git a/t/db_dependent/Koha/SearchEngine/Elasticsearch.t b/t/db_dependent/Koha/SearchEngine/Elasticsearch.t index 62d2291186..53a236a49d 100755 --- a/t/db_dependent/Koha/SearchEngine/Elasticsearch.t +++ b/t/db_dependent/Koha/SearchEngine/Elasticsearch.t @@ -17,7 +17,7 @@ use Modern::Perl; -use Test::More tests => 6; +use Test::More tests => 7; use Test::Exception; use t::lib::Mocks; @@ -29,6 +29,8 @@ use MARC::Record; use Try::Tiny; use List::Util qw( any ); +use C4::AuthoritiesMarc; + use Koha::SearchEngine::Elasticsearch; use Koha::SearchEngine::Elasticsearch::Search; @@ -850,4 +852,78 @@ subtest 'Koha::SearchEngine::Elasticsearch::marc_records_to_documents () authori }; +subtest 'Koha::SearchEngine::Elasticsearch::marc_records_to_documents with IncludeSeeFromInSearches' => sub { + + plan tests => 4; + + t::lib::Mocks::mock_preference('marcflavour', 'MARC21'); + t::lib::Mocks::mock_preference('IncludeSeeFromInSearches', '1'); + + my $builder = t::lib::TestBuilder->new; + my $auth_type = $builder->build_object({ + class => 'Koha::Authority::Types', + value => { + auth_tag_to_report => '150' + } + }); + my $authority_record = MARC::Record->new(); + $authority_record->append_fields( + MARC::Field->new(150, '', '', a => 'Foo'), + MARC::Field->new(450, '', '', a => 'Bar'), + ); + my $authid = AddAuthority($authority_record, undef, $auth_type->authtypecode); + + my @mappings = ( + { + name => 'subject', + type => 'string', + facet => 1, + suggestible => 1, + sort => undef, + searchable => 1, + marc_type => 'marc21', + marc_field => '650a', + } + ); + + my $se = Test::MockModule->new('Koha::SearchEngine::Elasticsearch'); + $se->mock('_foreach_mapping', sub { + my ($self, $sub) = @_; + + foreach my $map (@mappings) { + $sub->( + $map->{name}, + $map->{type}, + $map->{facet}, + $map->{suggestible}, + $map->{sort}, + $map->{searchable}, + $map->{marc_type}, + $map->{marc_field} + ); + } + }); + + my $see = Koha::SearchEngine::Elasticsearch::Search->new({ index => $Koha::SearchEngine::Elasticsearch::BIBLIOS_INDEX }); + + my $marc_record_1 = MARC::Record->new(); + $marc_record_1->leader(' cam 22 a 4500'); + $marc_record_1->append_fields( + MARC::Field->new('001', '123'), + MARC::Field->new('245', '', '', a => 'Title'), + MARC::Field->new('650', '', '', a => 'Foo', 9 => $authid), + MARC::Field->new('999', '', '', c => '1234567'), + ); + + # sort_fields will call this and use the actual db values unless we call it first + $see->get_elasticsearch_mappings(); + + my $docs = $see->marc_records_to_documents([$marc_record_1]); + + is_deeply($docs->[0]->{subject}, ['Foo', 'Bar'], 'subject should include "See from"'); + is_deeply($docs->[0]->{subject__facet}, ['Foo'], 'subject__facet should not include "See from"'); + is_deeply($docs->[0]->{subject__suggestion}, [{ input => 'Foo' }], 'subject__suggestion should not include "See from"'); + is_deeply($docs->[0]->{subject__sort}, ['Foo'], 'subject__sort should not include "See from"'); +}; + $schema->storage->txn_rollback; -- 2.20.1