Bug 18131: ES - Fix matching staged records
The code in C4::Matches::get_matches is terrible and a bug has been introduced
by bug 12478 because of its way to handle uniqueness.
If search engine is elastic, simple_search_compat returns array ref of MARC::Record,
used as a string for the key of the matches hashref we get things like
"MARC::Record=HASH(0x8f76ab0)".
Yes, terrible...
The file is never staged and we get an internal server error:
stage-marc-import.pl: Can't locate object method "fields" via package "MARC::Record=HASH(0x8f76ab0)" (perhaps you forgot to load "MARC::Record=HASH(0x8f76ab0)"?) at /home/vagrant/kohaclone/C4/Biblio.pm line 2691
To recreate the issue:
- Set SearchEngine == Elastic
- Create a matching rule on 999$c (you need to edit the existing one and specify
'Local-number' as search index, not 'local-number')
- Import a file with bibliographic records and use the matching rule you defined.
Test plan:
Import authority and bibliographic records with Zebra and Elastic using a matching rule.
Everything should work correctly.
Note: I found a bug when importing authorities using Elastic, see bug 17255 comment 38.
Signed-off-by: Nick Clemens <nick@bywatersolutions.com>
Signed-off-by: Julian Maurice <julian.maurice@biblibre.com>
Signed-off-by: Jonathan Druart <jonathan.druart@bugs.koha-community.org>
This commit is contained in:
parent
a081ed16c0
commit
eed1c91c8f
|
|
@ -619,7 +619,8 @@ sub get_matches {
|
|||
my $self = shift;
|
||||
my ($source_record, $max_matches) = @_;
|
||||
|
||||
my %matches = ();
|
||||
my $matches = {};
|
||||
my $marcframework_used = ''; # use the default framework
|
||||
|
||||
my $QParser;
|
||||
$QParser = C4::Context->queryparser if (C4::Context->preference('UseQueryParser'));
|
||||
|
|
@ -665,6 +666,27 @@ sub get_matches {
|
|||
my $searcher = Koha::SearchEngine::Search->new({index => $Koha::SearchEngine::BIBLIOS_INDEX});
|
||||
( $error, $searchresults, $total_hits ) =
|
||||
$searcher->simple_search_compat( $query, 0, $max_matches, undef, skip_normalize => 1 );
|
||||
|
||||
if ( defined $error ) {
|
||||
warn "search failed ($query) $error";
|
||||
}
|
||||
else {
|
||||
if ( C4::Context->preference('SearchEngine') eq 'Elasticsearch' ) {
|
||||
foreach my $matched ( @{$searchresults} ) {
|
||||
my ( $biblionumber_tag, $biblionumber_subfield ) = C4::Biblio::GetMarcFromKohaField( "biblio.biblionumber", $marcframework_used );
|
||||
my $id = $matched->field($biblionumber_tag)->subfield($biblionumber_subfield);
|
||||
$matches->{$id}->{score} += $matchpoint->{score};
|
||||
$matches->{$id}->{record} = $matched;
|
||||
}
|
||||
}
|
||||
else {
|
||||
foreach my $matched ( @{$searchresults} ) {
|
||||
$matches->{$matched}->{score} += $matchpoint->{'score'};
|
||||
$matches->{$matched}->{record} = $matched;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
elsif ( $self->{'record_type'} eq 'authority' ) {
|
||||
my $authresults;
|
||||
|
|
@ -687,41 +709,43 @@ sub get_matches {
|
|||
'AuthidAsc', 1
|
||||
);
|
||||
foreach my $result (@$authresults) {
|
||||
push @$searchresults, $result->{'authid'};
|
||||
}
|
||||
}
|
||||
|
||||
if ( defined $error ) {
|
||||
warn "search failed ($query) $error";
|
||||
}
|
||||
else {
|
||||
foreach my $matched ( @{$searchresults} ) {
|
||||
$matches{$matched} += $matchpoint->{'score'};
|
||||
my $id = $result->{authid};
|
||||
$matches->{$id}->{score} += $matchpoint->{'score'};
|
||||
$matches->{$id}->{record} = $id;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# get rid of any that don't meet the threshold
|
||||
%matches = map { ($matches{$_} >= $self->{'threshold'}) ? ($_ => $matches{$_}) : () } keys %matches;
|
||||
|
||||
# get rid of any that don't meet the required checks
|
||||
%matches = map { _passes_required_checks($source_record, $_, $self->{'required_checks'}) ? ($_ => $matches{$_}) : () }
|
||||
keys %matches unless ($self->{'record_type'} eq 'auth');
|
||||
$matches = { map { ($matches->{$_}->{score} >= $self->{'threshold'}) ? ($_ => $matches->{$_}) : () } keys %$matches };
|
||||
|
||||
my @results = ();
|
||||
if ($self->{'record_type'} eq 'biblio') {
|
||||
require C4::Biblio;
|
||||
foreach my $marcblob (keys %matches) {
|
||||
my $target_record = C4::Search::new_record_from_zebra('biblioserver',$marcblob);
|
||||
my $record_number;
|
||||
my $result = C4::Biblio::TransformMarcToKoha($target_record, '');
|
||||
$record_number = $result->{'biblionumber'};
|
||||
push @results, { 'record_id' => $record_number, 'score' => $matches{$marcblob} };
|
||||
# get rid of any that don't meet the required checks
|
||||
$matches = {
|
||||
map {
|
||||
_passes_required_checks( $source_record, $_, $self->{'required_checks'} )
|
||||
? ( $_ => $matches->{$_} )
|
||||
: ()
|
||||
} keys %$matches
|
||||
};
|
||||
|
||||
foreach my $id ( keys %$matches ) {
|
||||
my $target_record = C4::Search::new_record_from_zebra( 'biblioserver', $matches->{$id}->{record} );
|
||||
my $result = C4::Biblio::TransformMarcToKoha( $target_record, $marcframework_used );
|
||||
push @results, {
|
||||
record_id => $result->{biblionumber},
|
||||
score => $matches->{$id}->{score}
|
||||
};
|
||||
}
|
||||
} elsif ($self->{'record_type'} eq 'authority') {
|
||||
require C4::AuthoritiesMarc;
|
||||
foreach my $authid (keys %matches) {
|
||||
push @results, { 'record_id' => $authid, 'score' => $matches{$authid} };
|
||||
foreach my $id (keys %$matches) {
|
||||
push @results, {
|
||||
record_id => $id,
|
||||
score => $matches->{$id}->{score}
|
||||
};
|
||||
}
|
||||
}
|
||||
@results = sort {
|
||||
|
|
@ -732,7 +756,6 @@ sub get_matches {
|
|||
@results = @results[0..$max_matches-1];
|
||||
}
|
||||
return @results;
|
||||
|
||||
}
|
||||
|
||||
=head2 dump
|
||||
|
|
|
|||
Loading…
Reference in New Issue