Bug 12478: Move mapping attributes to the join table

To make things consistent, the attributes of the mappings (sort,
suggestible, facet) should be moved to the join tables
(search_marc_to_field).
Indeed the search_marc_map could represent a mapping for several search
fields with different attributes. Before this change it was not
possible.

Signed-off-by: Nick Clemens <nick@bywatersolutions.com>
Signed-off-by: Jesse Weaver <jweaver@bywatersolutions.com>
Signed-off-by: Tomas Cohen Arazi <tomascohen@theke.io>

Signed-off-by: Kyle M Hall <kyle@bywatersolutions.com>

Signed-off-by: Brendan Gallagher <brendan@bywatersolutions.com>
This commit is contained in:
Jonathan Druart 2015-10-12 16:46:16 +01:00 committed by Brendan Gallagher
parent 3e95923a8a
commit 24f72bd12a
4 changed files with 137 additions and 22 deletions

View file

@ -374,29 +374,38 @@ sub _foreach_mapping {
my ( $self, $sub ) = @_;
# TODO use a caching framework here
my $database = Koha::Database->new();
my $schema = $database->schema();
my $rs =
$schema->resultset('SearchMarcMap')
->search( { index_name => $self->index } );
for my $row ( $rs->all ) {
my $marc_type = $row->marc_type;
my $marc_field = $row->marc_field;
my $facet = $row->facet;
my $suggestible = $row->suggestible;
my $search_field = $row->search_fields();
my $sort = $row->sort();
for my $sf ( $search_field->all ) {
$sub->(
$sf->name,
$sf->type,
$facet,
$suggestible,
$sort,
$marc_type,
$marc_field,
);
my $search_fields = Koha::Database->schema->resultset('SearchField')->search(
{
'search_marc_map.index_name' => $self->index,
},
{ join => { search_marc_to_fields => 'search_marc_map' },
'+select' => [
'search_marc_to_fields.facet',
'search_marc_to_fields.suggestible',
'search_marc_to_fields.sort',
'search_marc_map.marc_type',
'search_marc_map.marc_field',
],
'+as' => [
'facet',
'suggestible',
'sort',
'marc_type',
'marc_field',
],
}
);
while ( my $search_field = $search_fields->next ) {
$sub->(
$search_field->name,
$search_field->type,
$search_field->get_column('facet'),
$search_field->get_column('suggestible'),
$search_field->get_column('sort'),
$search_field->get_column('marc_type'),
$search_field->get_column('marc_field'),
);
}
}

View file

@ -89,6 +89,24 @@ sub find {
return $object;
}
=head3 Koha::Objects->find_or_create();
my $object = Koha::Objects->find_or_create( $attrs );
=cut
sub find_or_create {
my ( $self, $params ) = @_;
my $result = $self->_resultset->find_or_create($params);
return unless $result;
my $object = $self->object_class->_new_from_dbic($result);
return $object;
}
=head3 Koha::Objects->search();
my @objects = Koha::Objects->search($params);

View file

@ -33,6 +33,11 @@ Koha::SearchField - Koha SearchField Object class
=cut
sub add_to_search_marc_maps {
my ( $self, $search_field, $params ) = @_;
return $self->_result()->add_to_search_marc_maps($search_field->_result, $params);
}
=head3 type
=cut

View file

@ -0,0 +1,83 @@
#!/usr/bin/perl
use Modern::Perl;
use C4::Context;
use YAML::Syck;
use Koha::SearchMarcMaps;
use Koha::SearchFields;
my $dbh = C4::Context->dbh;
$dbh->do(q|DROP TABLE IF EXISTS search_marc_to_field|);
$dbh->do(q|DROP TABLE IF EXISTS search_marc_map|);
$dbh->do(q|DROP TABLE IF EXISTS search_field|);
# This specifies the fields that will be stored in the search engine.
$dbh->do(q|
CREATE TABLE `search_field` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`name` varchar(255) NOT NULL COMMENT 'the name of the field as it will be stored in the search engine',
`label` varchar(255) NOT NULL COMMENT 'the human readable name of the field, for display',
`type` ENUM('string', 'date', 'number', 'boolean', 'sum') NOT NULL COMMENT 'what type of data this holds, relevant when storing it in the search engine',
PRIMARY KEY (`id`),
UNIQUE KEY (`name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
|);
# This contains a MARC field specifier for a given index, marc type, and marc
# field.
$dbh->do(q|
CREATE TABLE `search_marc_map` (
id int(11) NOT NULL AUTO_INCREMENT,
index_name ENUM('biblios','authorities') NOT NULL COMMENT 'what storage index this map is for',
marc_type ENUM('marc21', 'unimarc', 'normarc') NOT NULL COMMENT 'what MARC type this map is for',
marc_field VARCHAR(255) NOT NULL COMMENT 'the MARC specifier for this field',
PRIMARY KEY(`id`),
unique key( index_name, marc_field, marc_type),
INDEX (`index_name`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
|);
# This joins the two search tables together. We can have any combination:
# one marc field could have many search fields (maybe you want one value
# to go to 'author' and 'corporate-author) and many marc fields could go
# to one search field (e.g. all the various author fields going into
# 'author'.)
#
# a note about the sort field:
# * if all the entries for a mapping are 'null', nothing special is done with that mapping.
# * if any of the entries are not null, then a __sort field is created in ES for this mapping. In this case:
# * any mapping with sort == false WILL NOT get copied into a __sort field
# * any mapping with sort == true or is null WILL get copied into a __sort field
# * any sorts on the field name will be applied to $fieldname.'__sort' instead.
# this means that we can have search for author that includes 1xx, 245$c, and 7xx, but the sort only applies to 1xx.
$dbh->do(q|
CREATE TABLE `search_marc_to_field` (
search_marc_map_id int(11) NOT NULL,
search_field_id int(11) NOT NULL,
facet boolean DEFAULT FALSE COMMENT 'true if a facet field should be generated for this',
suggestible boolean DEFAULT FALSE COMMENT 'true if this field can be used to generate suggestions for browse',
sort boolean DEFAULT NULL COMMENT 'true/false creates special sort handling, null doesn''t',
PRIMARY KEY(search_marc_map_id, search_field_id),
FOREIGN KEY(search_marc_map_id) REFERENCES search_marc_map(id) ON DELETE CASCADE ON UPDATE CASCADE,
FOREIGN KEY(search_field_id) REFERENCES search_field(id) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
|);
my $mappings_yaml = C4::Context->config('intranetdir') . '/admin/searchengine/elasticsearch/mappings.yaml';
my $indexes = LoadFile( $mappings_yaml );
while ( my ( $index_name, $fields ) = each %$indexes ) {
while ( my ( $field_name, $data ) = each %$fields ) {
my $field_type = $data->{type};
my $field_label = $data->{label};
my $mappings = $data->{mappings};
my $search_field = Koha::SearchFields->find_or_create({ name => $field_name, label => $field_label, type => $field_type }, { key => 'name' });
for my $mapping ( @$mappings ) {
my $marc_field = Koha::SearchMarcMaps->find_or_create({ index_name => $index_name, marc_type => $mapping->{marc_type}, marc_field => $mapping->{marc_field} });
$search_field->add_to_search_marc_maps($marc_field, { facet => $mapping->{facet}, suggestible => $mapping->{suggestible}, sort => $mapping->{sort} } );
}
}
}