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

(-)a/Koha/SearchEngine/Elasticsearch.pm (-120 / +88 lines)
Lines 34-41 use Search::Elasticsearch; Link Here
34
use Try::Tiny;
34
use Try::Tiny;
35
use YAML::Syck;
35
use YAML::Syck;
36
36
37
use Data::Dumper;    # TODO remove
38
39
__PACKAGE__->mk_ro_accessors(qw( index ));
37
__PACKAGE__->mk_ro_accessors(qw( index ));
40
__PACKAGE__->mk_accessors(qw( sort_fields ));
38
__PACKAGE__->mk_accessors(qw( sort_fields ));
41
39
Lines 137-160 A hashref containing the settings is returned. Link Here
137
sub get_elasticsearch_settings {
135
sub get_elasticsearch_settings {
138
    my ($self) = @_;
136
    my ($self) = @_;
139
137
140
    # Ultimately this should come from a file or something, and not be
138
    # Use state to speed up repeated calls
141
    # hardcoded.
139
    state $settings = undef;
142
    my $settings = {
140
    if (!defined $settings) {
143
        index => {
141
        my $config_file = C4::Context->config('elasticsearch_index_config');
144
            analysis => {
142
        $config_file ||= C4::Context->config('intranetdir') . '/etc/searchengine/elasticsearch/index_config.yaml';
145
                analyzer => {
143
        $settings = LoadFile( $config_file );
146
                    analyser_phrase => {
144
    }
147
                        tokenizer => 'icu_tokenizer',
145
148
                        filter    => ['icu_folding'],
149
                    },
150
                    analyser_standard => {
151
                        tokenizer => 'icu_tokenizer',
152
                        filter    => ['icu_folding'],
153
                    },
154
                },
155
            }
156
        }
157
    };
158
    return $settings;
146
    return $settings;
159
}
147
}
160
148
Lines 170-285 created. Link Here
170
sub get_elasticsearch_mappings {
158
sub get_elasticsearch_mappings {
171
    my ($self) = @_;
159
    my ($self) = @_;
172
160
173
    # TODO cache in the object?
161
    # Use state to speed up repeated calls
174
    my $mappings = {
162
    state %all_mappings;
175
        data => {
163
    state %sort_fields;
176
            _all => {type => "string", analyzer => "analyser_standard"},
164
177
            properties => {
165
    if (!defined $all_mappings{$self->index}) {
178
                record => {
166
        $sort_fields{$self->index} = {};
179
                    store          => "true",
167
        my $mappings = {
180
                    include_in_all => JSON::false,
168
            data => _get_elasticsearch_mapping('general', '')
181
                    type           => "text",
169
        };
182
                },
170
        my $marcflavour = lc C4::Context->preference('marcflavour');
183
            }
171
        $self->_foreach_mapping(
184
        }
172
            sub {
185
    };
173
                my ( $name, $type, $facet, $suggestible, $sort, $marc_type ) = @_;
186
    my %sort_fields;
174
                return if $marc_type ne $marcflavour;
187
    my $marcflavour = lc C4::Context->preference('marcflavour');
175
                # TODO if this gets any sort of complexity to it, it should
188
    $self->_foreach_mapping(
176
                # be broken out into its own function.
189
        sub {
177
190
            my ( $name, $type, $facet, $suggestible, $sort, $marc_type ) = @_;
178
                # TODO be aware of date formats, but this requires pre-parsing
191
            return if $marc_type ne $marcflavour;
179
                # as ES will simply reject anything with an invalid date.
192
            # TODO if this gets any sort of complexity to it, it should
180
                my $es_type = 'text';
193
            # be broken out into its own function.
181
                if ($type eq 'boolean') {
194
182
                    $es_type = 'boolean';
195
            # TODO be aware of date formats, but this requires pre-parsing
183
                } elsif ($type eq 'number' || $type eq 'sum') {
196
            # as ES will simply reject anything with an invalid date.
184
                    $es_type = 'integer';
197
            my $es_type =
185
                } elsif ($type eq 'isbn' || $type eq 'stdno') {
198
              $type eq 'boolean'
186
                    $es_type = 'stdno';
199
              ? 'boolean'
187
                }
200
              : 'text';
201
202
            if ($es_type eq 'boolean') {
203
                $mappings->{data}{properties}{$name} = _elasticsearch_mapping_for_boolean( $name, $es_type, $facet, $suggestible, $sort, $marc_type );
204
                return; #Boolean cannot have facets nor sorting nor suggestions
205
            } else {
206
                $mappings->{data}{properties}{$name} = _elasticsearch_mapping_for_default( $name, $es_type, $facet, $suggestible, $sort, $marc_type );
207
            }
208
188
209
            if ($facet) {
189
                $mappings->{data}{properties}{$name} = _get_elasticsearch_mapping('search', $es_type);
210
                $mappings->{data}{properties}{ $name . '__facet' } = {
190
211
                    type  => "keyword",
191
                if ($facet) {
212
                };
192
                    $mappings->{data}{properties}{ $name . '__facet' } = _get_elasticsearch_mapping('facet', $es_type);
213
            }
193
                }
214
            if ($suggestible) {
194
                if ($suggestible) {
215
                $mappings->{data}{properties}{ $name . '__suggestion' } = {
195
                    $mappings->{data}{properties}{ $name . '__suggestion' } = _get_elasticsearch_mapping('suggestible', $es_type);                    
216
                    type => 'completion',
196
                }
217
                    analyzer => 'simple',
197
                # Sort is a bit special as it can be true, false, undef.
218
                    search_analyzer => 'simple',
198
                # We care about "true" or "undef",
219
                };
199
                # "undef" means to do the default thing, which is make it sortable.
220
            }
200
                if (!defined $sort || $sort) {
221
            # Sort is a bit special as it can be true, false, undef.
201
                    $mappings->{data}{properties}{ $name . '__sort' } = _get_elasticsearch_mapping('sort', $es_type);
222
            # We care about "true" or "undef",
202
                    $sort_fields{$self->index}{$name} = 1;
223
            # "undef" means to do the default thing, which is make it sortable.
203
                }
224
            if ($sort || !defined $sort) {
225
                $mappings->{data}{properties}{ $name . '__sort' } = {
226
                    search_analyzer => "analyser_phrase",
227
                    analyzer  => "analyser_phrase",
228
                    type            => "text",
229
                    include_in_all  => JSON::false,
230
                    fields          => {
231
                        phrase => {
232
                            type            => "keyword",
233
                        },
234
                    },
235
                };
236
                $sort_fields{$name} = 1;
237
            }
204
            }
238
        }
205
        );
239
    );
206
        $all_mappings{$self->index} = $mappings;
240
    $self->sort_fields(\%sort_fields);
207
    }
241
    return $mappings;
208
    $self->sort_fields(\%{$sort_fields{$self->index}});
209
210
    return $all_mappings{$self->index};
242
}
211
}
243
212
244
=head2 _elasticsearch_mapping_for_*
213
=head2 _get_elasticsearch_mapping
245
214
246
Get the ES mappings for the given data type or a special mapping case
215
Get the ES mappings for the given purpose and data type
247
216
248
Receives the same parameters from the $self->_foreach_mapping() dispatcher
217
$mapping = _get_elasticsearch_mapping('search', 'text');
249
218
250
=cut
219
=cut
251
220
252
sub _elasticsearch_mapping_for_boolean {
221
sub _get_elasticsearch_mapping {
253
    my ( $name, $type, $facet, $suggestible, $sort, $marc_type ) = @_;
254
222
255
    return {
223
    my ( $purpose, $type ) = @_;
256
        type            => $type,
257
        null_value      => 0,
258
    };
259
}
260
224
261
sub _elasticsearch_mapping_for_default {
225
    # Use state to speed up repeated calls
262
    my ( $name, $type, $facet, $suggestible, $sort, $marc_type ) = @_;
226
    state $settings = undef; 
263
227
    if (!defined $settings) {
264
    return {
228
        my $config_file = C4::Context->config('elasticsearch_field_config');
265
        search_analyzer => "analyser_standard",
229
        $config_file ||= C4::Context->config('intranetdir') . '/etc/searchengine/elasticsearch/field_config.yaml';
266
        analyzer        => "analyser_standard",
230
        $settings = LoadFile( $config_file );
267
        type            => $type,
231
    }
268
        fields          => {
232
269
            phrase => {
233
    if (!defined $settings->{$purpose}) {
270
                search_analyzer => "analyser_phrase",
234
        die "Field purpose $purpose not defined in field config";
271
                analyzer        => "analyser_phrase",
235
    }
272
                type            => "text",
236
    if ($type eq '') {
273
            },
237
        return $settings->{$purpose};
274
            raw => {
238
    }
275
                type    => "keyword",
239
    if (defined $settings->{$purpose}{$type}) {
276
            }
240
        return $settings->{$purpose}{$type};
277
        },
241
    }
278
    };
242
    if (defined $settings->{$purpose}{'default'}) {
243
        return $settings->{$purpose}{'default'};
244
    }
245
    return undef;
279
}
246
}
280
247
281
sub reset_elasticsearch_mappings {
248
sub reset_elasticsearch_mappings {
282
    my $mappings_yaml = C4::Context->config('intranetdir') . '/admin/searchengine/elasticsearch/mappings.yaml';
249
    my ( $reset_fields ) = @_;
250
    my $mappings_yaml = C4::Context->config('intranetdir') . '/etc/searchengine/elasticsearch/mappings.yaml';
283
    my $indexes = LoadFile( $mappings_yaml );
251
    my $indexes = LoadFile( $mappings_yaml );
284
252
285
    while ( my ( $index_name, $fields ) = each %$indexes ) {
253
    while ( my ( $index_name, $fields ) = each %$indexes ) {
Lines 349-358 sub get_fixer_rules { Link Here
349
            if ($type eq 'sum' ) {
317
            if ($type eq 'sum' ) {
350
                push @rules, "sum('$name')";
318
                push @rules, "sum('$name')";
351
            }
319
            }
352
            if ($self->sort_fields()->{$name}) {
320
            my $sort_fields = $self->sort_fields();
353
                if ($sort || !defined $sort) {
321
            if (defined $sort_fields->{$name} && $sort_fields->{$name}) {
354
                    push @rules, "marc_map('$marc_field','${name}__sort.\$append', $options)";
322
                push @rules, "marc_map('$marc_field','${name}__sort.\$append')";
355
                }
323
                push @rules, "join_field('${name}__sort',' ')";
356
            }
324
            }
357
        }
325
        }
358
    );
326
    );
(-)a/admin/searchengine/elasticsearch/mappings.pl (+2 lines)
Lines 102-107 elsif( $op eq 'reset' ) { Link Here
102
    my $sure = $input->param('i_know_what_i_am_doing');
102
    my $sure = $input->param('i_know_what_i_am_doing');
103
    if ( $sure ) {
103
    if ( $sure ) {
104
        Koha::SearchMarcMaps->search->delete;
104
        Koha::SearchMarcMaps->search->delete;
105
        my $reset_fields = $input->param('reset_fields');
106
        Koha::SearchFields->delete if ( $reset_fields );
105
        Koha::SearchEngine::Elasticsearch->reset_elasticsearch_mappings;
107
        Koha::SearchEngine::Elasticsearch->reset_elasticsearch_mappings;
106
    }
108
    }
107
}
109
}
(-)a/debian/templates/koha-conf-site.xml.in (+11 lines)
Lines 319-328 __END_SRU_PUBLICSERVER__ Link Here
319
 <plack_max_requests>50</plack_max_requests>
319
 <plack_max_requests>50</plack_max_requests>
320
 <plack_workers>2</plack_workers>
320
 <plack_workers>2</plack_workers>
321
321
322
 <!-- Elasticsearch Configuration -->
322
 <elasticsearch>
323
 <elasticsearch>
323
     <server>localhost:9200</server>
324
     <server>localhost:9200</server>
324
     <index_name>koha___KOHASITE__</index_name>
325
     <index_name>koha___KOHASITE__</index_name>
325
 </elasticsearch>
326
 </elasticsearch>
327
 <!-- Uncomment the following line if you want to override the Elasticsearch default index settings -->
328
 <!-- <elasticsearch_index_config>__KOHA_CONF_DIR__/searchengine/elasticsearch/index_config.yaml</elasticsearch_index_config> -->
329
 <!-- Uncomment the following line if you want to override the Elasticsearch default field settings -->
330
 <!-- <elasticsearch_field_config>__KOHA_CONF_DIR__/searchengine/elasticsearch/field_config.yaml</elasticsearch_field_config> -->
331
 <!-- Uncomment the following line if you want to override the Elasticsearch index default settings. 
332
      Note that any changes made to the mappings file only take effect if you reset the mappings in 
333
      by visiting /cgi-bin/koha/admin/searchengine/elasticsearch/mappings.pl?op=reset&i_know_what_i_am_doing=1&reset_fields=1.
334
      Resetting mappings will override any changes made in the Search engine configuration UI.
335
 -->
336
 <!-- <elasticsearch_index_mappings>__KOHA_CONF_DIR__/searchengine/elasticsearch/mappings.yaml</elasticsearch_index_mappings> -->
326
337
327
 <interlibrary_loans>
338
 <interlibrary_loans>
328
     <!-- Path to where Illbackends are located on the system
339
     <!-- Path to where Illbackends are located on the system
(-)a/etc/koha-conf.xml (+109 lines)
Lines 150-155 __PAZPAR2_TOGGLE_XML_POST__ Link Here
150
 <plack_max_requests>50</plack_max_requests>
150
 <plack_max_requests>50</plack_max_requests>
151
 <plack_workers>2</plack_workers>
151
 <plack_workers>2</plack_workers>
152
152
153
 <!-- Elasticsearch Configuration -->
154
 <elasticsearch>
155
     <server>__ELASTICSEARCH_SERVERS__</server>      <!-- may be repeated to include all servers on your cluster -->
156
     <index_name>__ELASTICSEARCH_INDEX__</index_name>  <!-- should be unique amongst all the indices on your cluster. _biblios and _authorities will be appended. -->
157
 </elasticsearch>
158
 <!-- Uncomment the following line if you want to override the Elasticsearch default index settings -->
159
 <!-- <elasticsearch_index_config>__KOHA_CONF_DIR__/searchengine/elasticsearch/index_config.yaml</elasticsearch_index_config> -->
160
 <!-- Uncomment the following line if you want to override the Elasticsearch default field settings -->
161
 <!-- <elasticsearch_field_config>__KOHA_CONF_DIR__/searchengine/elasticsearch/field_config.yaml</elasticsearch_field_config> -->
162
 <!-- Uncomment the following line if you want to override the Elasticsearch index default settings. 
163
      Note that any changes made to the mappings file only take effect if you reset the mappings in 
164
      by visiting /cgi-bin/koha/admin/searchengine/elasticsearch/mappings.pl?op=reset&i_know_what_i_am_doing=1&reset_fields=1.
165
      Resetting mappings will override any changes made in the Search engine configuration UI.
166
 -->
167
 <!-- <elasticsearch_index_mappings>__KOHA_CONF_DIR__/searchengine/elasticsearch/mappings.yaml</elasticsearch_index_mappings> -->
168
153
 <interlibrary_loans>
169
 <interlibrary_loans>
154
     <!-- Path to where Illbackends are located on the system
170
     <!-- Path to where Illbackends are located on the system
155
          - This setting should normally not be touched -->
171
          - This setting should normally not be touched -->
Lines 171-175 __PAZPAR2_TOGGLE_XML_POST__ Link Here
171
     <partner_code>ILLLIBS</partner_code>
187
     <partner_code>ILLLIBS</partner_code>
172
 </interlibrary_loans>
188
 </interlibrary_loans>
173
189
190
 <!-- PageObject tests connect to these servers -->
191
 <testservers>
192
    <opac>
193
        <base_url>http://__WEBSERVER_IP__:__WEBSERVER_PORT__</base_url>
194
    </opac>
195
    <staff>
196
        <base_url>http://__WEBSERVER_IP__:__WEBSERVER_PORT_LIBRARIAN__</base_url>
197
    </staff>
198
    <rest>
199
        <base_url>http://__WEBSERVER_IP__:__WEBSERVER_PORT_LIBRARIAN__</base_url>
200
    </rest>
201
 </testservers>
202
 <pos>
203
    <CPU>
204
        <!-- Default payment server configuration -->
205
        <!-- Delivered by CPU: -->
206
        <source></source>                           <!-- Source id -->
207
        <secretKey></secretKey>                     <!-- Secret key for generating SHA-256 hash -->
208
        <url></url>                                 <!-- Address to the cash register server -->
209
        <!-- SSL certificates -->
210
        <ssl_cert></ssl_cert>                       <!-- SSL certificate path -->
211
        <ssl_key></ssl_key>                         <!-- SSL key path -->
212
        <ssl_ca_file></ssl_ca_file>                 <!-- CA certificate path -->
213
214
        <!-- Per branch payment server configuration -->
215
        <branchcode>
216
            <!--
217
                Example:
218
219
                <CPL>
220
                    <source></source>
221
                    <secretKey></secretKey>
222
                    <url></url>
223
                    <ssl_cert></ssl_cert>
224
                    <ssl_key></ssl_key>
225
                    <ssl_ca_file></ssl_ca_file>
226
                </CPL>
227
                <MPL>
228
                    ...
229
                </MPL>
230
            -->
231
        </branchcode>
232
233
        <!-- Koha settings -->
234
        <mode></mode>                               <!-- Use 2 for synchronized mode -->
235
        <notificationAddress></notificationAddress> <!-- https://server/api/v1/payments/pos/cpu/{invoicenumber}/report -->
236
        <!-- Replace "server" with your server address, but keep {invoicenumber} as it is (it will be converted later into real id) -->
237
  </CPU>
238
 </pos>
239
 <online_payments>
240
    <CPU>
241
        <!-- Delivered by CPU: -->
242
        <source></source>                           <!-- Source id -->
243
        <secretKey></secretKey>                     <!-- Secret key for generating SHA-256 hash -->
244
        <url></url>                                 <!-- Address to the online payments server -->
245
246
        <mode></mode>                               <!-- Use 3 for online payments -->
247
248
        <!-- Replace "server" with your server address, but keep {invoicenumber} as it is (it will be converted later into real id) -->
249
        <notificationAddress></notificationAddress> <!-- https://server/api/v1/payments/online/cpu/{invoicenumber}/report -->
250
        <returnAddress></returnAddress> <!-- Where to redirect user from CPU online shop after the payment is complete?
251
                                            e.g. https://server/cgi-bin/koha/opac-paycollect.pl -->
252
    </CPU>
253
 </online_payments>
254
   <!-- sendOverdueBills module and sap ftp configurations -->
255
 <sendoverduebills_pathtoxml></sendoverduebills_pathtoxml> <!-- All xml files created by this module goes in this directory -->
256
 <!-- Path to xml schema including filename -->
257
 <sendoverduebills_pathtoxsd></sendoverduebills_pathtoxsd>
258
 <sendoverduebills_xmlwritemode></sendoverduebills_xmlwritemode> <!-- Use value 1 only if you need to read xml manually! Default value is 0 -->
259
 <sap_ftp_host></sap_ftp_host> <!-- Ftp host ip address -->
260
 <sap_ftp_port></sap_ftp_port> <!-- Ftp host port -->
261
 <sap_ftp_timeout></sap_ftp_timeout> <!-- Ftp connection timeout -->
262
 <sap_ftp_ispassive></sap_ftp_ispassive> <!-- 1 for passive mode, 0 for active mode -->
263
 <sap_ftp_user></sap_ftp_user> <!-- Ftp username -->
264
 <sap_ftp_pw></sap_ftp_pw> <!-- Ftp password for username -->
265
 <sap_use_sftp></sap_use_sftp> <!-- 1 use sftp, 0 use ftp -->
266
267
 <!-- Connection to ssn server for billing -->
268
 <ssnProvider>
269
    <url></url> <!-- base URL of ssn-service -->
270
    <interface></interface> <!-- This is either directDB or FindSSN (recommended) for Outi billing, always directDB for Billing Manager  -->
271
    <directDB>    
272
        <host></host>
273
        <port></port>
274
        <user></user>
275
        <password></password>
276
    </directDB>
277
    <findSSN>
278
        <user></user>
279
        <password></password>
280
    </findSSN>
281
 </ssnProvider>
282
174
</config>
283
</config>
175
</yazgfs>
284
</yazgfs>
(-)a/etc/searchengine/elasticsearch/field_config.yaml (+61 lines)
Line 0 Link Here
1
---
2
# General field configuration
3
general:
4
  _all: 
5
    type: string
6
    analyzer: analyser_standard
7
  properties:
8
    record:
9
      store: true
10
      type: text
11
# Search fields
12
search: 
13
  boolean:
14
    type: boolean
15
    null_value: false
16
  integer:
17
    type: integer
18
    null_value: 0
19
  stdno:
20
    type: text
21
    analyzer: analyser_stdno
22
    search_analyzer: analyser_stdno
23
    fields:
24
      phrase:
25
        type: text
26
        analyzer: analyser_stdno
27
        search_analyzer: analyser_stdno
28
      raw:
29
        type: keyword
30
    copy_to: _all
31
  default:
32
    type: text
33
    analyzer: analyser_standard
34
    search_analyzer: analyser_standard
35
    fields: 
36
      phrase:
37
        type: text
38
        analyzer: analyser_phrase
39
        search_analyzer: analyser_phrase
40
      raw:
41
        type: keyword
42
    copy_to: all
43
# Facets
44
facet:
45
  default:
46
    type: keyword
47
# Suggestible
48
suggestible:
49
  default:
50
    type: completion
51
    analyzer: simple
52
    search_analyzer: simple
53
# Sort
54
sort:
55
  default:
56
    type: text
57
    analyzer: analyser_phrase
58
    search_analyzer: analyser_phrase
59
    fields:
60
      phrase:
61
        type: keyword
(-)a/etc/searchengine/elasticsearch/index_config.yaml (+34 lines)
Line 0 Link Here
1
---
2
# Index configuration that defines how different analyzers work. 
3
index:
4
  analysis:
5
    analyzer:
6
      # Phrase analyzer is used for phrases (phrase match, sorting)
7
      analyser_phrase:
8
        tokenizer: keyword
9
        filter:
10
          - icu_folding
11
        char_filter: 
12
          - punctuation
13
      analyser_standard:
14
        tokenizer: icu_tokenizer
15
        filter:
16
          - icu_folding
17
      analyser_stdno:
18
        tokenizer: whitespace
19
        filter: 
20
          - icu_folding
21
        char_filter: 
22
          - punctuation
23
    normalizer:
24
      normalizer_keyword:
25
        type: custom
26
        filter: 
27
          - icu_folding
28
    char_filter:
29
      # The punctuation filter is used to remove any punctuation chars in fields that don't use icu_tokenizer.
30
      punctuation:
31
        type: pattern_replace
32
        # The pattern contains all ASCII punctuation characters.
33
        pattern: '([\x00-\x1F,\x21-\x2F,\x3A-\x40,\x5B-\x60,\x7B-\x89,\x8B,\x8D,\x8F,\x90-\x99,\x9B,\x9D,\xA0-\xBF,\xD7,\xF7])'
34
        replacement: ''
(-)a/admin/searchengine/elasticsearch/mappings.yaml (-3 / +4 lines)
Lines 1-4 Link Here
1
---
1
---
2
# Basic mappings from MARC fields to Elasticsearch fields. 
2
authorities:
3
authorities:
3
  Corporate-name-see-also-from:
4
  Corporate-name-see-also-from:
4
    label: Corporate-name-see-also-from
5
    label: Corporate-name-see-also-from
Lines 1549-1555 biblios: Link Here
1549
        marc_type: unimarc
1550
        marc_type: unimarc
1550
        sort: ~
1551
        sort: ~
1551
        suggestible: ''
1552
        suggestible: ''
1552
    type: ''
1553
    type: 'stdno'
1553
  isbn:
1554
  isbn:
1554
    label: isbn
1555
    label: isbn
1555
    mappings:
1556
    mappings:
Lines 1568-1574 biblios: Link Here
1568
        marc_type: unimarc
1569
        marc_type: unimarc
1569
        sort: ~
1570
        sort: ~
1570
        suggestible: ''
1571
        suggestible: ''
1571
    type: ''
1572
    type: 'isbn'
1572
  issn:
1573
  issn:
1573
    label: issn
1574
    label: issn
1574
    mappings:
1575
    mappings:
Lines 1587-1593 biblios: Link Here
1587
        marc_type: unimarc
1588
        marc_type: unimarc
1588
        sort: ~
1589
        sort: ~
1589
        suggestible: ''
1590
        suggestible: ''
1590
    type: ''
1591
    type: 'stdno'
1591
  issues:
1592
  issues:
1592
    label: issues
1593
    label: issues
1593
    mappings:
1594
    mappings:
(-)a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/searchengine/elasticsearch/mappings.tt (-1 / +1 lines)
Lines 88-94 a.add, a.delete { Link Here
88
88
89
    <h1>Search engine configuration</h1>
89
    <h1>Search engine configuration</h1>
90
    <div class="warning">
90
    <div class="warning">
91
        Warning: Any modification in these configurations will need a total reindexation to be fully taken into account !
91
        Warning: Any modification of this configuration requires a complete index rebuild to be fully taken into account!
92
    </div>
92
    </div>
93
    [% IF errors %]
93
    [% IF errors %]
94
        <div class="error">
94
        <div class="error">
(-)a/t/Koha/SearchEngine/Elasticsearch.t (-7 / +30 lines)
Lines 17-23 Link Here
17
17
18
use Modern::Perl;
18
use Modern::Perl;
19
19
20
use Test::More tests => 1;
20
use Test::More tests => 3;
21
use Test::Exception;
21
use Test::Exception;
22
22
23
use t::lib::Mocks;
23
use t::lib::Mocks;
Lines 33-39 subtest '_read_configuration() tests' => sub { Link Here
33
33
34
    # 'elasticsearch' missing in configuration
34
    # 'elasticsearch' missing in configuration
35
    throws_ok {
35
    throws_ok {
36
        $configuration = Koha::SearchEngine::Elasticsearch::_read_configuration;
36
        $configuration = Koha::SearchEngine::Elasticsearch::_read_configuration();
37
    }
37
    }
38
    'Koha::Exceptions::Config::MissingEntry',
38
    'Koha::Exceptions::Config::MissingEntry',
39
      'Configuration problem, exception thrown';
39
      'Configuration problem, exception thrown';
Lines 46-52 subtest '_read_configuration() tests' => sub { Link Here
46
    # 'elasticsearch' present but no 'server' entry
46
    # 'elasticsearch' present but no 'server' entry
47
    t::lib::Mocks::mock_config( 'elasticsearch', {} );
47
    t::lib::Mocks::mock_config( 'elasticsearch', {} );
48
    throws_ok {
48
    throws_ok {
49
        $configuration = Koha::SearchEngine::Elasticsearch::_read_configuration;
49
        $configuration = Koha::SearchEngine::Elasticsearch::_read_configuration();
50
    }
50
    }
51
    'Koha::Exceptions::Config::MissingEntry',
51
    'Koha::Exceptions::Config::MissingEntry',
52
      'Configuration problem, exception thrown';
52
      'Configuration problem, exception thrown';
Lines 59-65 subtest '_read_configuration() tests' => sub { Link Here
59
    # 'elasticsearch' and 'server' entries present, but no 'index_name'
59
    # 'elasticsearch' and 'server' entries present, but no 'index_name'
60
    t::lib::Mocks::mock_config( 'elasticsearch', { server => 'a_server' } );
60
    t::lib::Mocks::mock_config( 'elasticsearch', { server => 'a_server' } );
61
    throws_ok {
61
    throws_ok {
62
        $configuration = Koha::SearchEngine::Elasticsearch::_read_configuration;
62
        $configuration = Koha::SearchEngine::Elasticsearch::_read_configuration();
63
    }
63
    }
64
    'Koha::Exceptions::Config::MissingEntry',
64
    'Koha::Exceptions::Config::MissingEntry',
65
      'Configuration problem, exception thrown';
65
      'Configuration problem, exception thrown';
Lines 72-78 subtest '_read_configuration() tests' => sub { Link Here
72
    # Correct configuration, only one server
72
    # Correct configuration, only one server
73
    t::lib::Mocks::mock_config( 'elasticsearch',  { server => 'a_server', index_name => 'index' } );
73
    t::lib::Mocks::mock_config( 'elasticsearch',  { server => 'a_server', index_name => 'index' } );
74
74
75
    $configuration = Koha::SearchEngine::Elasticsearch::_read_configuration;
75
    $configuration = Koha::SearchEngine::Elasticsearch::_read_configuration();
76
    is( $configuration->{index_name}, 'index', 'Index configuration parsed correctly' );
76
    is( $configuration->{index_name}, 'index', 'Index configuration parsed correctly' );
77
    is_deeply( $configuration->{nodes}, ['a_server'], 'Server configuration parsed correctly' );
77
    is_deeply( $configuration->{nodes}, ['a_server'], 'Server configuration parsed correctly' );
78
78
Lines 80-86 subtest '_read_configuration() tests' => sub { Link Here
80
    my @servers = ('a_server', 'another_server');
80
    my @servers = ('a_server', 'another_server');
81
    t::lib::Mocks::mock_config( 'elasticsearch', { server => \@servers, index_name => 'index' } );
81
    t::lib::Mocks::mock_config( 'elasticsearch', { server => \@servers, index_name => 'index' } );
82
82
83
    $configuration = Koha::SearchEngine::Elasticsearch::_read_configuration;
83
    $configuration = Koha::SearchEngine::Elasticsearch::_read_configuration();
84
    is( $configuration->{index_name}, 'index', 'Index configuration parsed correctly' );
84
    is( $configuration->{index_name}, 'index', 'Index configuration parsed correctly' );
85
    is_deeply( $configuration->{nodes}, \@servers , 'Server configuration parsed correctly' );
85
    is_deeply( $configuration->{nodes}, \@servers , 'Server configuration parsed correctly' );
86
};
86
};
87
- 
87
88
subtest 'get_elasticsearch_settings() tests' => sub {
89
90
    plan tests => 1;
91
92
    my $settings;
93
94
    # test reading index settings
95
    my $es = Koha::SearchEngine::Elasticsearch->new( {index => $Koha::SearchEngine::Elasticsearch::BIBLIOS_INDEX} );
96
    $settings = $es->get_elasticsearch_settings();
97
    is( $settings->{index}{analysis}{analyzer}{analyser_phrase}{tokenizer}, 'keyword', 'Index settings parsed correctly' );
98
};
99
100
subtest 'get_elasticsearch_mappings() tests' => sub {
101
102
    plan tests => 1;
103
104
    my $mappings;
105
106
    # test reading mappings
107
    my $es = Koha::SearchEngine::Elasticsearch->new( {index => $Koha::SearchEngine::Elasticsearch::BIBLIOS_INDEX} );
108
    $mappings = $es->get_elasticsearch_mappings();
109
    is( $mappings->{data}{_all}{type}, 'string', 'Field mappings parsed correctly' );
110
};

Return to bug 20073