View | Details | Raw Unified | Return to bug 12478
Collapse All | Expand All

(-)a/Koha/ElasticSearch.pm (-22 / +31 lines)
Lines 374-402 sub _foreach_mapping { Link Here
374
    my ( $self, $sub ) = @_;
374
    my ( $self, $sub ) = @_;
375
375
376
    # TODO use a caching framework here
376
    # TODO use a caching framework here
377
    my $database = Koha::Database->new();
377
    my $search_fields = Koha::Database->schema->resultset('SearchField')->search(
378
    my $schema   = $database->schema();
378
        {
379
    my $rs =
379
            'search_marc_map.index_name' => $self->index,
380
      $schema->resultset('SearchMarcMap')
380
        },
381
      ->search( { index_name => $self->index } );
381
        {   join => { search_marc_to_fields => 'search_marc_map' },
382
    for my $row ( $rs->all ) {
382
            '+select' => [
383
        my $marc_type = $row->marc_type;
383
                'search_marc_to_fields.facet',
384
        my $marc_field = $row->marc_field;
384
                'search_marc_to_fields.suggestible',
385
        my $facet = $row->facet;
385
                'search_marc_to_fields.sort',
386
        my $suggestible = $row->suggestible;
386
                'search_marc_map.marc_type',
387
        my $search_field = $row->search_fields();
387
                'search_marc_map.marc_field',
388
        my $sort = $row->sort();
388
            ],
389
        for my $sf ( $search_field->all ) {
389
            '+as'     => [
390
            $sub->(
390
                'facet',
391
                $sf->name,
391
                'suggestible',
392
                $sf->type,
392
                'sort',
393
                $facet,
393
                'marc_type',
394
                $suggestible,
394
                'marc_field',
395
                $sort,
395
            ],
396
                $marc_type,
397
                $marc_field,
398
            );
399
        }
396
        }
397
    );
398
399
    while ( my $search_field = $search_fields->next ) {
400
        $sub->(
401
            $search_field->name,
402
            $search_field->type,
403
            $search_field->get_column('facet'),
404
            $search_field->get_column('suggestible'),
405
            $search_field->get_column('sort'),
406
            $search_field->get_column('marc_type'),
407
            $search_field->get_column('marc_field'),
408
        );
400
    }
409
    }
401
}
410
}
402
411
(-)a/Koha/Objects.pm (+18 lines)
Lines 91-96 sub find { Link Here
91
    return $object;
91
    return $object;
92
}
92
}
93
93
94
=head3 Koha::Objects->find_or_create();
95
96
my $object = Koha::Objects->find_or_create( $attrs );
97
98
=cut
99
100
sub find_or_create {
101
    my ( $self, $params ) = @_;
102
103
    my $result = $self->_resultset->find_or_create($params);
104
105
    return unless $result;
106
107
    my $object = $self->object_class->_new_from_dbic($result);
108
109
    return $object;
110
}
111
94
=head3 Koha::Objects->search();
112
=head3 Koha::Objects->search();
95
113
96
my @objects = Koha::Objects->search($params);
114
my @objects = Koha::Objects->search($params);
(-)a/Koha/SearchField.pm (+5 lines)
Lines 33-38 Koha::SearchField - Koha SearchField Object class Link Here
33
33
34
=cut
34
=cut
35
35
36
sub add_to_search_marc_maps {
37
    my ( $self, $search_field, $params ) = @_;
38
    return $self->_result()->add_to_search_marc_maps($search_field->_result, $params);
39
}
40
36
=head3 type
41
=head3 type
37
42
38
=cut
43
=cut
(-)a/installer/data/mysql/atomicupdate/elastic_search.perl (+83 lines)
Line 0 Link Here
1
#!/usr/bin/perl
2
3
use Modern::Perl;
4
5
use C4::Context;
6
use YAML::Syck;
7
8
use Koha::SearchMarcMaps;
9
use Koha::SearchFields;
10
11
my $dbh = C4::Context->dbh;
12
13
$dbh->do(q|DROP TABLE IF EXISTS search_marc_to_field|);
14
$dbh->do(q|DROP TABLE IF EXISTS search_marc_map|);
15
$dbh->do(q|DROP TABLE IF EXISTS search_field|);
16
17
# This specifies the fields that will be stored in the search engine.
18
$dbh->do(q|
19
    CREATE TABLE `search_field` (
20
      `id` int(11) NOT NULL AUTO_INCREMENT,
21
      `name` varchar(255) NOT NULL COMMENT 'the name of the field as it will be stored in the search engine',
22
      `label` varchar(255) NOT NULL COMMENT 'the human readable name of the field, for display',
23
      `type` ENUM('string', 'date', 'number', 'boolean', 'sum') NOT NULL COMMENT 'what type of data this holds, relevant when storing it in the search engine',
24
      PRIMARY KEY (`id`),
25
      UNIQUE KEY (`name`)
26
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
27
|);
28
29
# This contains a MARC field specifier for a given index, marc type, and marc
30
# field.
31
$dbh->do(q|
32
    CREATE TABLE `search_marc_map` (
33
        id int(11) NOT NULL AUTO_INCREMENT,
34
        index_name ENUM('biblios','authorities') NOT NULL COMMENT 'what storage index this map is for',
35
        marc_type ENUM('marc21', 'unimarc', 'normarc') NOT NULL COMMENT 'what MARC type this map is for',
36
        marc_field VARCHAR(255) NOT NULL COMMENT 'the MARC specifier for this field',
37
        PRIMARY KEY(`id`),
38
        unique key( index_name, marc_field, marc_type),
39
        INDEX (`index_name`)
40
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
41
|);
42
43
# This joins the two search tables together. We can have any combination:
44
# one marc field could have many search fields (maybe you want one value
45
# to go to 'author' and 'corporate-author) and many marc fields could go
46
# to one search field (e.g. all the various author fields going into
47
# 'author'.)
48
#
49
# a note about the sort field:
50
# * if all the entries for a mapping are 'null', nothing special is done with that mapping.
51
# * if any of the entries are not null, then a __sort field is created in ES for this mapping. In this case:
52
#   * any mapping with sort == false WILL NOT get copied into a __sort field
53
#   * any mapping with sort == true or is null WILL get copied into a __sort field
54
#   * any sorts on the field name will be applied to $fieldname.'__sort' instead.
55
# this means that we can have search for author that includes 1xx, 245$c, and 7xx, but the sort only applies to 1xx.
56
$dbh->do(q|
57
    CREATE TABLE `search_marc_to_field` (
58
        search_marc_map_id int(11) NOT NULL,
59
        search_field_id int(11) NOT NULL,
60
        facet boolean DEFAULT FALSE COMMENT 'true if a facet field should be generated for this',
61
        suggestible boolean DEFAULT FALSE COMMENT 'true if this field can be used to generate suggestions for browse',
62
        sort boolean DEFAULT NULL COMMENT 'true/false creates special sort handling, null doesn''t',
63
        PRIMARY KEY(search_marc_map_id, search_field_id),
64
        FOREIGN KEY(search_marc_map_id) REFERENCES search_marc_map(id) ON DELETE CASCADE ON UPDATE CASCADE,
65
        FOREIGN KEY(search_field_id) REFERENCES search_field(id) ON DELETE CASCADE ON UPDATE CASCADE
66
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci
67
|);
68
69
my $mappings_yaml = C4::Context->config('intranetdir') . '/admin/searchengine/elasticsearch/mappings.yaml';
70
my $indexes = LoadFile( $mappings_yaml );
71
72
while ( my ( $index_name, $fields ) = each %$indexes ) {
73
    while ( my ( $field_name, $data ) = each %$fields ) {
74
        my $field_type = $data->{type};
75
        my $field_label = $data->{label};
76
        my $mappings = $data->{mappings};
77
        my $search_field = Koha::SearchFields->find_or_create({ name => $field_name, label => $field_label, type => $field_type }, { key => 'name' });
78
        for my $mapping ( @$mappings ) {
79
            my $marc_field = Koha::SearchMarcMaps->find_or_create({ index_name => $index_name, marc_type => $mapping->{marc_type}, marc_field => $mapping->{marc_field} });
80
            $search_field->add_to_search_marc_maps($marc_field, { facet => $mapping->{facet}, suggestible => $mapping->{suggestible}, sort => $mapping->{sort} } );
81
        }
82
    }
83
}
(-)a/installer/data/mysql/updatedatabase.pl (-34 lines)
Lines 10945-10983 if ( CheckVersion($DBversion) ) { Link Here
10945
    SetVersion($DBversion);
10945
    SetVersion($DBversion);
10946
}
10946
}
10947
10947
10948
$DBversion = "XXX";
10949
if ( C4::Context->preference("Version") < TransformToNum($DBversion) ) {
10950
    my $installer = C4::Installer->new();
10951
    my $full_path = C4::Context->config('intranetdir') . "/installer/data/$installer->{dbms}/elasticsearch_mapping.sql";
10952
    my $error     = $installer->load_sql($full_path);
10953
    warn $error if $error;
10954
    print "Upgrade to $DBversion done (Bug 12478 - set up elasticsearch tables)\n";
10955
    SetVersion($DBversion);
10956
}
10957
10958
$DBversion = "XXX";
10959
if ( C4::Context->preference("Version") < TransformToNum($DBversion) ) {
10960
    $dbh->do(q|
10961
        ALTER TABLE search_marc_to_field DROP FOREIGN KEY search_marc_to_field_ibfk_1
10962
    |);
10963
    $dbh->do(q|
10964
        ALTER TABLE search_marc_to_field
10965
        ADD CONSTRAINT search_marc_to_field_ibfk_1 FOREIGN KEY (`search_marc_map_id`) REFERENCES `search_marc_map` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
10966
    |);
10967
    $dbh->do(q|
10968
        ALTER TABLE search_marc_map DROP KEY index_name_2
10969
    |);
10970
    $dbh->do(q|
10971
        ALTER TABLE search_field ADD COLUMN label VARCHAR(255) AFTER name
10972
    |);
10973
    $dbh->do(q|
10974
        UPDATE search_field SET label=name
10975
    |);
10976
10977
    print "Upgrade to $DBversion done (Bug 12478/14899 - DB Changes to the elasticsearch tables)\n";
10978
    SetVersion($DBversion);
10979
}
10980
10981
# DEVELOPER PROCESS, search for anything to execute in the db_update directory
10948
# DEVELOPER PROCESS, search for anything to execute in the db_update directory
10982
# SEE bug 13068
10949
# SEE bug 13068
10983
# if there is anything in the atomicupdate, read and execute it.
10950
# if there is anything in the atomicupdate, read and execute it.
10984
- 

Return to bug 12478