From a106accfe8d7e4cd380b2e7e316e50466f358e19 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=utf8 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 Signed-off-by: Jonathan Druart Signed-off-by: Kyle M Hall --- 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 9ed7b45bea..ecdb060a48 100644 --- a/Koha/Filter/MARC/EmbedSeeFromHeadings.pm +++ b/Koha/Filter/MARC/EmbedSeeFromHeadings.pm @@ -59,22 +59,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; @@ -86,7 +95,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); @@ -101,9 +109,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 74250f3e48..7d54e6448d 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; @@ -640,6 +641,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.39.5