From 1ba9fadce5f6a356b451602730a0023dcb14f020 Mon Sep 17 00:00:00 2001 From: Jonathan Druart Date: Wed, 8 Mar 2017 12:04:46 -0300 Subject: [PATCH] Bug 18235: ES - Facets configurable This patch adds a new section 'Facet order' in the Biblio tab of the 'Search engine configuration' admin page of the Elastic mappings. The idea is to let the librarians define the facet to display and order them as their needs. The ergonomic is not perfect and I am open to any suggestions. Test plan: Move up and down the field list to order the facets Hide/show some facets At the OPAC and the staff interface you should see the changes on the search result page. Signed-off-by: Nick Clemens --- Koha/SearchEngine/Elasticsearch.pm | 26 +++++++- Koha/SearchEngine/Elasticsearch/Search.pm | 30 +++++---- admin/searchengine/elasticsearch/mappings.pl | 34 ++++++++--- admin/searchengine/elasticsearch/mappings.yaml | 9 +++ .../admin/searchengine/elasticsearch/mappings.tt | 71 +++++++++++++++++++--- 5 files changed, 138 insertions(+), 32 deletions(-) diff --git a/Koha/SearchEngine/Elasticsearch.pm b/Koha/SearchEngine/Elasticsearch.pm index de4b18ce4d..b76b484aa3 100644 --- a/Koha/SearchEngine/Elasticsearch.pm +++ b/Koha/SearchEngine/Elasticsearch.pm @@ -283,7 +283,15 @@ sub reset_elasticsearch_mappings { 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' }); + my $facet_order = $data->{facet_order}; + my $search_field = Koha::SearchFields->find_or_create({ name => $field_name }); + $search_field->update( + { + label => $field_label, + type => $field_type, + facet_order => $facet_order + } + ); 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} || 0, suggestible => $mapping->{suggestible} || 0, sort => $mapping->{sort} } ); @@ -479,6 +487,22 @@ sub process_error { return "Unable to perform your search. Please try again.\n"; } +sub get_facetable_fields { + my ($self) = @_; + + # These should correspond to the ES field names, as opposed to the CCL + # things that zebra uses. + my @search_field_names = qw( author itype location su-geo se subject ccode holdingbranch homebranch ); + my @faceted_fields = Koha::SearchFields->search( + { name => { -in => \@search_field_names }, facet_order => { '!=' => undef } }, { order_by => ['facet_order'] } + ); + my @not_faceted_fields = Koha::SearchFields->search( + { name => { -in => \@search_field_names }, facet_order => undef }, { order_by => ['facet_order'] } + ); + # This could certainly be improved + return ( @faceted_fields, @not_faceted_fields ); +} + 1; __END__ diff --git a/Koha/SearchEngine/Elasticsearch/Search.pm b/Koha/SearchEngine/Elasticsearch/Search.pm index 4d584f7906..c29e421cb3 100644 --- a/Koha/SearchEngine/Elasticsearch/Search.pm +++ b/Koha/SearchEngine/Elasticsearch/Search.pm @@ -423,18 +423,25 @@ sub _convert_facets { # These should correspond to the ES field names, as opposed to the CCL # things that zebra uses. - # TODO let the library define the order using the interface. - my %type_to_label = ( - author => { order => 1, label => 'Authors', }, - itype => { order => 2, label => 'ItemTypes', }, - location => { order => 3, label => 'Location', }, - 'su-geo' => { order => 4, label => 'Places', }, - se => { order => 5, label => 'Series', }, - subject => { order => 6, label => 'Topics', }, - ccode => { order => 7, label => 'CollectionCodes',}, - holdingbranch => { order => 8, label => 'HoldingLibrary' }, - homebranch => { order => 9, label => 'HomeLibrary' } + my %type_to_label; + my %label = ( + author => 'Authors', + itype => 'ItemTypes', + location => 'Location', + 'su-geo' => 'Places', + se => 'Series', + subject => 'Topics', + ccode => 'CollectionCodes', + holdingbranch => 'HoldingLibrary', + homebranch => 'HomeLibrary', ); + my @facetable_fields = + Koha::SearchEngine::Elasticsearch->get_facetable_fields; + for my $f (@facetable_fields) { + next unless defined $f->facet_order; + $type_to_label{ $f->name } = + { order => $f->facet_order, label => $label{ $f->name } }; + } # We also have some special cases, e.g. itypes that need to show the # value rather than the code. @@ -492,5 +499,4 @@ sub _convert_facets { return \@facets; } - 1; diff --git a/admin/searchengine/elasticsearch/mappings.pl b/admin/searchengine/elasticsearch/mappings.pl index 7d63002919..8fb117ab40 100755 --- a/admin/searchengine/elasticsearch/mappings.pl +++ b/admin/searchengine/elasticsearch/mappings.pl @@ -17,6 +17,7 @@ use Modern::Perl; use CGI; +use List::Util qw( first ); use C4::Koha; use C4::Output; use C4::Auth; @@ -48,16 +49,17 @@ if ( $op eq 'edit' ) { $schema->storage->txn_begin; - my @field_name = $input->param('search_field_name'); - my @field_label = $input->param('search_field_label'); - my @field_type = $input->param('search_field_type'); + my @field_name = $input->multi_param('search_field_name'); + my @field_label = $input->multi_param('search_field_label'); + my @field_type = $input->multi_param('search_field_type'); - my @index_name = $input->param('mapping_index_name'); - my @search_field_name = $input->param('mapping_search_field_name'); - my @mapping_sort = $input->param('mapping_sort'); - my @mapping_facet = $input->param('mapping_facet'); - my @mapping_suggestible = $input->param('mapping_suggestible'); - my @mapping_marc_field = $input->param('mapping_marc_field'); + my @index_name = $input->multi_param('mapping_index_name'); + my @search_field_name = $input->multi_param('mapping_search_field_name'); + my @mapping_sort = $input->multi_param('mapping_sort'); + my @mapping_facet = $input->multi_param('mapping_facet'); + my @mapping_suggestible = $input->multi_param('mapping_suggestible'); + my @mapping_marc_field = $input->multi_param('mapping_marc_field'); + my @faceted_field_names = $input->multi_param('display_facet'); eval { @@ -68,10 +70,14 @@ if ( $op eq 'edit' ) { my $search_field = Koha::SearchFields->find( { name => $field_name }, { key => 'name' } ); $search_field->label($field_label); $search_field->type($field_type); + my $facet_order = first { $faceted_field_names[$_] eq $field_name } 0 .. $#faceted_field_names; + $search_field->facet_order(defined $facet_order ? $facet_order + 1 : undef); $search_field->store; } Koha::SearchMarcMaps->search( { marc_type => $marc_type, } )->delete; + my @facetable_fields = Koha::SearchEngine::Elasticsearch->get_facetable_fields(); + my @facetable_field_names = map { $_->name } @facetable_fields; for my $i ( 0 .. scalar(@index_name) - 1 ) { my $index_name = $index_name[$i]; @@ -81,6 +87,7 @@ if ( $op eq 'edit' ) { my $mapping_suggestible = $mapping_suggestible[$i]; my $mapping_sort = $mapping_sort[$i]; $mapping_sort = undef if $mapping_sort eq 'undef'; + $mapping_facet = ( grep {/^$search_field_name$/} @facetable_field_names ) ? $mapping_facet : 0; my $search_field = Koha::SearchFields->find({ name => $search_field_name }, { key => 'name' }); # TODO Check mapping format @@ -118,15 +125,20 @@ for my $index_name (qw| biblios authorities |) { ); my @mappings; + my @facetable_fields = Koha::SearchEngine::Elasticsearch->get_facetable_fields(); + my @facetable_field_names = map { $_->name } @facetable_fields; + while ( my $s = $search_fields->next ) { + my $name = $s->name; push @mappings, - { search_field_name => $s->name, + { search_field_name => $name, search_field_label => $s->label, search_field_type => $s->type, marc_field => $s->get_column('marc_field'), sort => $s->get_column('sort') // 'undef', # To avoid warnings "Use of uninitialized value in lc" suggestible => $s->get_column('suggestible'), facet => $s->get_column('facet'), + is_facetable => ( grep {/^$name$/} @facetable_field_names ) ? 1 : 0, }; } @@ -135,9 +147,11 @@ for my $index_name (qw| biblios authorities |) { my $search_fields = $schema->resultset('SearchField')->search; my @all_search_fields = $search_fields->search( {}, { order_by => ['name'] } ); +my @facetable_fields = Koha::SearchEngine::Elasticsearch->get_facetable_fields(); $template->param( indexes => \@indexes, all_search_fields => \@all_search_fields, + facetable_fields => \@facetable_fields, messages => \@messages, ); diff --git a/admin/searchengine/elasticsearch/mappings.yaml b/admin/searchengine/elasticsearch/mappings.yaml index 25a1cc7b93..0b35055226 100644 --- a/admin/searchengine/elasticsearch/mappings.yaml +++ b/admin/searchengine/elasticsearch/mappings.yaml @@ -1194,6 +1194,7 @@ biblios: sort: 0 suggestible: 0 type: string + facet_order: 1 bgf-number: label: bgf-number mappings: @@ -1274,6 +1275,7 @@ biblios: sort: ~ suggestible: '' type: '' + facet_order: 7 control-number: label: control-number mappings: @@ -1462,6 +1464,7 @@ biblios: sort: ~ suggestible: '' type: string + facet_order: 8 homebranch: label: HomeLibrary mappings: @@ -1481,6 +1484,7 @@ biblios: sort: ~ suggestible: '' type: string + facet_order: 9 identifier-standard: label: identifier-standard mappings: @@ -1655,6 +1659,7 @@ biblios: sort: ~ suggestible: '' type: string + facet_order: 2 lc-cardnumber: label: lc-cardnumber mappings: @@ -1774,6 +1779,7 @@ biblios: sort: ~ suggestible: '' type: '' + facet_order: 3 material-type: label: material-type mappings: @@ -2005,6 +2011,7 @@ biblios: sort: ~ suggestible: '' type: string + facet_order: 5 su-geo: label: su-geo mappings: @@ -2024,6 +2031,7 @@ biblios: sort: ~ suggestible: '' type: string + facet_order: 4 subject: label: subject mappings: @@ -2248,6 +2256,7 @@ biblios: sort: ~ suggestible: '1' type: string + facet_order: 6 suppress: label: suppress mappings: diff --git a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/searchengine/elasticsearch/mappings.tt b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/searchengine/elasticsearch/mappings.tt index 25535d9c2c..a40dabaea8 100644 --- a/koha-tmpl/intranet-tmpl/prog/en/modules/admin/searchengine/elasticsearch/mappings.tt +++ b/koha-tmpl/intranet-tmpl/prog/en/modules/admin/searchengine/elasticsearch/mappings.tt @@ -50,6 +50,9 @@ } ); } }); + $("#facet_biblios > table").tableDnD( { + onDragClass: "dragClass", + } ); });