@@ -, +, @@ Elasticsearch 100 $a Foo 400 $a Bar cataloguing plugin 'Foo' but not when searching 'Bar' 'Foo' and also when searching 'Bar' --- Koha/Filter/MARC/EmbedSeeFromHeadings.pm | 20 ++++-- Koha/SearchEngine/Elasticsearch.pm | 49 +++++++++++++++ t/db_dependent/Koha/SearchEngine/Elasticsearch.t | 78 +++++++++++++++++++++++- 3 files changed, 140 insertions(+), 7 deletions(-) --- a/Koha/Filter/MARC/EmbedSeeFromHeadings.pm +++ a/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,7 +109,7 @@ sub _processrecord { $newfield->delete_subfield( code => '9' ); push @newfields, $newfield if (scalar($newfield->subfields()) > 0); } - $record->append_fields(@newfields); } - return $record; + + return @newfields; } --- a/Koha/SearchEngine/Elasticsearch.pm +++ a/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}; --- a/t/db_dependent/Koha/SearchEngine/Elasticsearch.t +++ a/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; --