1 package Koha::QueryParser::Driver::PQF;
3 # This file is part of Koha.
5 # Copyright 2012 C & P Bibliography Services
7 # Koha is free software; you can redistribute it and/or modify it
8 # under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 3 of the License, or
10 # (at your option) any later version.
12 # Koha is distributed in the hope that it will be useful, but
13 # WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU General Public License for more details.
17 # You should have received a copy of the GNU General Public License
18 # along with Koha; if not, see <http://www.gnu.org/licenses>.
20 use base qw(OpenILS::QueryParser Class::Accessor);
25 use Module::Load::Conditional qw(can_load);
26 use Koha::QueryParser::Driver::PQF::Util;
27 use Koha::QueryParser::Driver::PQF::query_plan;
28 use Koha::QueryParser::Driver::PQF::query_plan::facet;
29 use Koha::QueryParser::Driver::PQF::query_plan::filter;
30 use Koha::QueryParser::Driver::PQF::query_plan::modifier;
31 use Koha::QueryParser::Driver::PQF::query_plan::node;
32 use Koha::QueryParser::Driver::PQF::query_plan::node::atom;
33 use Koha::QueryParser::Driver::PQF::query_plan::node::atom;
38 Koha::QueryParser::Driver::PQF - QueryParser driver for PQF
42 use Koha::QueryParser::Driver::PQF;
43 my $QParser = Koha::QueryParser::Driver::PQF->new(%args);
47 Main entrypoint into the QueryParser PQF driver. PQF is the Prefix Query
48 Language, the syntax used to serialize Z39.50 queries.
52 In order to simplify Bib-1 attribute mapping, this driver uses Class::Accessor
53 for accessing the following maps:
57 =item B<bib1_field_map> - search class/field Bib-1 mappings
59 =item B<bib1_modifier_map> - search modifier mappings
61 =item B<bib1_filter_map> - search filter mappings
63 =item B<bib1_relevance_bump_map> - relevance bump mappings
69 __PACKAGE__->mk_accessors(qw(bib1_field_map bib1_modifier_map bib1_filter_map bib1_relevance_bump_map));
77 Overridden accessor method for Class::Accessor. (Do not call directly)
83 return $self->_map(@_);
88 Overridden mutator method for Class::Accessor. (Do not call directly)
94 return $self->_map(@_);
97 =head2 add_bib1_field_map
99 $QParser->add_bib1_field_map($class => $field => $server => \%attributes);
101 $QParser->add_bib1_field_map('author' => 'personal' => 'biblioserver' =>
104 Adds a search field<->bib1 attribute mapping for the specified server. The
105 %attributes hash contains maps Bib-1 Attributes to the appropropriate
106 values. Not all attributes must be specified.
110 sub add_bib1_field_map {
111 my ($self, $class, $field, $server, $attributes) = @_;
113 $self->add_search_field( $class => $field );
114 $self->add_search_field_alias( $class => $field => $field );
115 return $self->_add_field_mapping($self->bib1_field_map, $class, $field, $server, $attributes);
118 =head2 add_bib1_modifier_map
120 $QParser->add_bib1_modifier_map($name => $server => \%attributes);
122 $QParser->add_bib1_modifier_map('ascending' => 'biblioserver' =>
125 Adds a search modifier<->bib1 attribute mapping for the specified server. The
126 %attributes hash contains maps Bib-1 Attributes to the appropropriate
127 values. Not all attributes must be specified.
131 sub add_bib1_modifier_map {
132 my ($self, $name, $server, $attributes) = @_;
134 $self->add_search_modifier( $name );
136 return $self->_add_mapping($self->bib1_modifier_map, $name, $server, $attributes);
139 =head2 add_bib1_filter_map
141 $QParser->add_bib1_filter_map($name => $server => \%attributes);
143 $QParser->add_bib1_filter_map('date' => 'biblioserver' =>
144 { 'callback' => &_my_callback });
146 Adds a search filter<->bib1 attribute mapping for the specified server. The
147 %attributes hash maps Bib-1 Attributes to the appropropriate values and
148 provides a callback for the filter. Not all attributes must be specified.
152 sub add_bib1_filter_map {
153 my ($self, $name, $server, $attributes) = @_;
155 $self->add_search_filter( $name, $attributes->{'callback'} );
157 return $self->_add_mapping($self->bib1_filter_map, $name, $server, $attributes);
160 =head2 add_relevance_bump
162 $QParser->add_relevance_bump($class, $field, $server, $multiplier, $active);
163 $QParser->add_relevance_bump('title' => 'exact' => 'biblioserver' => 34, 1);
165 Add a relevance bump to the specified field. When searching for a class without
166 any fields, all the relevance bumps for the specified class will be 'OR'ed
171 sub add_relevance_bump {
172 my ($self, $class, $field, $server, $multiplier, $active) = @_;
173 my $attributes = { '9' => $multiplier, '2' => '102', 'active' => $active };
175 $self->add_search_field( $class => $field );
176 return $self->_add_field_mapping($self->bib1_relevance_bump_map, $class, $field, $server, $attributes);
182 my $pqf = $QParser->target_syntax($server, [$query]);
183 my $pqf = $QParser->target_syntax('biblioserver', 'author|personal:smith');
184 print $pqf; # assuming all the indexes are configured,
185 # prints '@attr 1=1003 @attr 4=6 "smith"'
187 Transforms the current or specified query into a PQF query string for the
193 my ($self, $server, $query) = @_;
195 $self->parse($query) if $query;
196 warn "QP query for $server: " . $self->query . "\n" if $self->debug;
197 $pqf = $self->parse_tree->target_syntax($server);
198 warn "PQF query: $pqf\n" if $self->debug;
205 =head2 date_filter_target_callback
207 $QParser->add_bib1_filter_map($server, { 'target_syntax_callback' => \&Koha::QueryParser::Driver::PQF::date_filter_target_callback, '1' => 'pubdate' });
209 Callback for date filters. Note that although the first argument is the QParser
210 object, this is technically not an object-oriented routine. This has no
211 real-world implications.
215 sub date_filter_target_callback {
216 my ($QParser, $filter, $params, $negate, $server) = @_;
217 my $attr_string = $QParser->bib1_mapping_by_name( 'filter', $filter, $server )->{'attr_string'};
219 foreach my $datespec (@$params) {
222 if ($datespec =~ m/(.*)-(.*)/) {
224 $datepqf .= $attr_string . ' @attr 2=4 "' . $1 . '"';
227 $datepqf .= $attr_string . ' @attr 2=2 "' . $2 . '"';
228 $datepqf = ' @and ' . $datepqf if $1;
231 $datepqf .= $attr_string . ' "' . $datespec . '"';
234 $pqf = ' @or ' . ($negate ? '@not @attr 1=_ALLRECORDS @attr 2=103 "" ' : '') . $pqf if $pqf;
242 return $self->_map('bib1_field_map', $map);
244 Retrieves or sets a map.
249 my ($self, $name, $map) = @_;
250 $self->custom_data->{$name} ||= {};
251 $self->custom_data->{$name} = $map if ($map);
252 return $self->custom_data->{$name};
257 return $self->_add_mapping($map, $name, $server, $attributes)
259 Adds a mapping. Note that this is not used for mappings relating to fields.
264 my ($self, $map, $name, $server, $attributes) = @_;
266 my $attr_string = Koha::QueryParser::Driver::PQF::Util::attributes_to_attr_string($attributes);
267 $attributes->{'attr_string'} = $attr_string;
269 $map->{'by_name'}{$name}{$server} = $attributes;
270 $map->{'by_attr'}{$server}{$attr_string} = { 'name' => $name, %$attributes };
275 =head2 _add_field_mapping
277 return $self->_add_field_mapping($map, $class, $field, $server, $attributes)
279 Adds a mapping for field-related data.
283 sub _add_field_mapping {
284 my ($self, $map, $class, $field, $server, $attributes) = @_;
285 my $attr_string = Koha::QueryParser::Driver::PQF::Util::attributes_to_attr_string($attributes);
286 $attributes->{'attr_string'} = $attr_string;
288 $map->{'by_name'}{$class}{$field}{$server} = $attributes;
289 $map->{'by_attr'}{$server}{$attr_string} = { 'classname' => $class, 'field' => $field, %$attributes };
294 =head2 bib1_mapping_by_name
296 my $attributes = $QParser->bib1_mapping_by_name($type, $name[, $subname], $server);
297 my $attributes = $QParser->bib1_mapping_by_name('field', 'author', 'personal', 'biblioserver');
298 my $attributes = $QParser->bib1_mapping_by_name('filter', 'pubdate', 'biblioserver');
300 Retrieve the Bib-1 attribute set associated with the specified mapping.
303 sub bib1_mapping_by_name {
305 my ($self, $type, $name, $field) = @_;
307 return unless ($server && $name);
308 return unless ($type eq 'field' || $type eq 'modifier' || $type eq 'filter' || $type eq 'relevance_bump');
309 if ($type eq 'field' || $type eq 'relevance_bump') {
310 # Unfortunately field is a special case thanks to the class->field hierarchy
311 return $self->_map('bib1_' . $type . '_map')->{'by_name'}{$name}{$field}{$server} if $field;
312 return $self->_map('bib1_' . $type . '_map')->{'by_name'}{$name};
314 return $self->_map('bib1_' . $type . '_map')->{'by_name'}{$name}{$server};
318 =head2 bib1_mapping_by_attr
320 my $field = $QParser->bib1_mapping_by_attr($type, $server, \%attr);
321 my $field = $QParser->bib1_mapping_by_attr('field', 'biblioserver', {'1' => '1004'});
322 print $field->{'classname'}; # prints "author"
323 print $field->{'field'}; # prints "personal"
325 Retrieve the search field/modifier/filter used for the specified Bib-1 attribute set.
329 sub bib1_mapping_by_attr {
330 my ($self, $type, $server, $attributes) = @_;
331 return unless ($server && $attributes);
333 my $attr_string = Koha::QueryParser::Driver::PQF::Util::attributes_to_attr_string($attributes);
335 return $self->bib1_mapping_by_attr_string($type, $server, $attr_string);
338 =head2 bib1_mapping_by_attr_string
340 my $field = $QParser->bib1_mapping_by_attr_string($type, $server, $attr_string);
341 my $field = $QParser->bib1_mapping_by_attr_string('field', 'biblioserver', '@attr 1=1004');
342 print $field->{'classname'}; # prints "author"
343 print $field->{'field'}; # prints "personal"
345 Retrieve the search field/modifier/filter used for the specified Bib-1 attribute string
350 sub bib1_mapping_by_attr_string {
351 my ($self, $type, $server, $attr_string) = @_;
352 return unless ($server && $attr_string);
353 return unless ($type eq 'field' || $type eq 'modifier' || $type eq 'filter' || $type eq 'relevance_bump');
355 return $self->_map('bib1_' . $type . '_map')->{'by_attr'}{$server}{$attr_string};
358 =head2 clear_all_configuration
360 $QParser->clear_all_configuration
362 Clear all configuration. This is a highly destructive method. You may
367 sub clear_all_configuration {
369 %OpenILS::QueryParser::parser_config = (
370 'OpenILS::QueryParser' => {
390 =head2 clear_all_mappings
392 $QParser->clear_all_mappings
394 Clear all bib-1 mappings.
398 sub clear_all_mappings {
401 foreach my $name (qw(field modifier filter relevance_bump)) {
402 $self->custom_data->{'bib1_' . $name . '_map'} = { };
408 =head2 _canonicalize_field_map
410 Convert a field map into its canonical form for serialization. Used only for
411 fields and relevance bumps.
415 sub _canonicalize_field_map {
416 my ( $map, $aliases ) = @_;
417 my $canonical_map = {};
419 foreach my $class ( keys %{ $map->{'by_name'} } ) {
420 $canonical_map->{$class} ||= {};
421 foreach my $field ( keys %{ $map->{'by_name'}->{$class} } ) {
424 'label' => ucfirst($field),
428 my $server ( keys %{ $map->{'by_name'}->{$class}->{$field} } )
430 $field_map->{'bib1_mapping'} ||= {};
431 $field_map->{'bib1_mapping'}->{$server} =
432 $map->{'by_name'}->{$class}->{$field}->{$server};
433 delete $field_map->{'bib1_mapping'}->{$server}->{'attr_string'}
435 $field_map->{'bib1_mapping'}->{$server}
440 $field_map->{'aliases'} = [];
441 foreach my $alias ( @{ $aliases->{$class}->{$field} } ) {
442 push @{ $field_map->{'aliases'} },
446 $canonical_map->{$class}->{$field} = $field_map;
449 return $canonical_map;
452 =head2 _canonicalize_map
454 Convert a map into its canonical form for serialization. Not used for fields.
458 sub _canonicalize_map {
460 my $canonical_map = {};
462 foreach my $name ( keys %{ $map->{'by_name'} } ) {
463 $canonical_map->{$name} = {
464 'label' => ucfirst($name),
468 foreach my $server ( keys %{ $map->{'by_name'}->{$name} } ) {
469 $canonical_map->{$name}->{'bib1_mapping'}->{$server} =
470 $map->{'by_name'}->{$name}->{$server};
471 delete $canonical_map->{$name}->{'bib1_mapping'}->{$server}
474 $canonical_map->{$name}->{'bib1_mapping'}->{$server}
479 return $canonical_map;
482 =head2 serialize_mappings
484 my $yaml = $QParser->serialize_mappings;
485 my $json = $QParser->serialize_mappings('json');
487 Serialize Bib-1 mappings to YAML or JSON.
491 sub serialize_mappings {
492 my ( $self, $format ) = @_;
496 $config->{'field_mappings'} =
497 _canonicalize_field_map( $self->bib1_field_map,
498 $self->search_field_aliases );
499 $config->{'modifier_mappings'} =
500 _canonicalize_map( $self->bib1_modifier_map );
501 $config->{'filter_mappings'} = _canonicalize_map( $self->bib1_filter_map );
502 $config->{'relevance_bumps'} =
503 _canonicalize_field_map( $self->bib1_relevance_bump_map );
505 if ( $format eq 'json' && can_load( modules => { 'JSON' => undef } ) ) {
506 return JSON::to_json($config);
508 elsif ( can_load( modules => { 'YAML::Any' => undef } ) ) {
509 return YAML::Any::Dump($config);
516 $QParser->initialize( { 'bib1_field_mappings' => \%bib1_field_mappings,
517 'search_field_alias_mappings' => \%search_field_alias_mappings,
518 'bib1_modifier_mappings' => \%bib1_modifier_mappings,
519 'bib1_filter_mappings' => \%bib1_filter_mappings,
520 'relevance_bumps' => \%relevance_bumps });
522 Initialize the QueryParser mapping tables based on the provided configuration.
523 This method was written to play nice with YAML configuration files loaded by load_config.
528 my ( $self, $args ) = @_;
530 my $field_mappings = $args->{'field_mappings'};
531 my $modifier_mappings = $args->{'modifier_mappings'};
532 my $filter_mappings = $args->{'filter_mappings'};
533 my $relbumps = $args->{'relevance_bumps'};
534 my ( $server, $bib1_mapping );
535 foreach my $class ( keys %$field_mappings ) {
536 foreach my $field ( keys %{ $field_mappings->{$class} } ) {
537 if ( $field_mappings->{$class}->{$field}->{'enabled'} ) {
538 while ( ( $server, $bib1_mapping ) =
540 %{ $field_mappings->{$class}->{$field}->{'bib1_mapping'} } )
542 $self->add_bib1_field_map(
543 $class => $field => $server => $bib1_mapping );
545 $self->add_search_field_alias( $class => $field =>
546 $field_mappings->{$class}->{$field}->{'index'} );
548 @{ $field_mappings->{$class}->{$field}->{'aliases'} } )
552 $field_mappings->{$class}->{$field}->{'index'} );
553 $self->add_search_field_alias( $class => $field => $alias );
558 foreach my $modifier ( keys %$modifier_mappings ) {
559 if ( $modifier_mappings->{$modifier}->{'enabled'} ) {
560 while ( ( $server, $bib1_mapping ) =
561 each %{ $modifier_mappings->{$modifier}->{'bib1_mapping'} } )
563 $self->add_bib1_modifier_map(
564 $modifier => $server => $bib1_mapping );
568 foreach my $filter ( keys %$filter_mappings ) {
569 if ( $filter_mappings->{$filter}->{'enabled'} ) {
570 while ( ( $server, $bib1_mapping ) =
571 each %{ $filter_mappings->{$filter}->{'bib1_mapping'} } )
573 if ( $bib1_mapping->{'target_syntax_callback'} eq
574 'date_filter_target_callback' )
576 $bib1_mapping->{'target_syntax_callback'} =
577 \&Koha::QueryParser::Driver::PQF::date_filter_target_callback;
579 $self->add_bib1_filter_map(
580 $filter => $server => $bib1_mapping );
584 foreach my $class ( keys %$relbumps ) {
585 foreach my $field ( keys %{ $relbumps->{$class} } ) {
586 if ( $relbumps->{$class}->{$field}->{'enabled'} ) {
587 while ( ( $server, $bib1_mapping ) =
588 each %{ $relbumps->{$class}->{$field}->{'bib1_mapping'} } )
590 $self->add_relevance_bump(
591 $class => $field => $server => $bib1_mapping,
603 $QParser->load_config($file_name);
605 Load a YAML file with a parser configuration. The YAML file should match the following format:
633 1: Date-of-acquisition
635 target_syntax_callback: date_filter_target_callback
653 my ($self, $file) = @_;
655 return unless ($file && -f $file);
656 my $config = YAML::Any::LoadFile($file);
657 return unless ($config);
658 $self->initialize($config);
666 This routine initializes the QueryParser driver with a reasonable set of
667 defaults. This is intended only for testing. Although such test stubs are
668 generally not included in Koha, this type of test stub is used by other
669 QueryParser implementations, and it seems sensible to maintain consistency
677 $self->default_search_class( 'keyword' );
679 $self->add_bib1_field_map('keyword' => 'abstract' => 'biblioserver' => { '1' => '62' } );
680 $self->add_search_field_alias( 'keyword' => 'abstract' => 'ab' );
681 $self->add_bib1_field_map('keyword' => '' => 'biblioserver' => { '1' => '1016' } );
682 $self->add_search_field_alias( 'keyword' => '' => 'kw' );
683 $self->add_bib1_field_map('author' => '' => 'biblioserver' => { '1' => '1003' } );
684 $self->add_search_field_alias( 'author' => '' => 'au' );
685 $self->add_bib1_field_map('author' => 'personal' => 'biblioserver' => { '1' => '1004' } );
686 $self->add_bib1_field_map('author' => 'corporate' => 'biblioserver' => { '1' => '1005' } );
687 $self->add_search_field_alias( 'author' => 'corporate' => 'cpn' );
688 $self->add_bib1_field_map('author' => 'conference' => 'biblioserver' => { '1' => '1006' } );
689 $self->add_search_field_alias( 'author' => 'conference' => 'cfn' );
690 $self->add_bib1_field_map('keyword' => 'local-classification' => 'biblioserver' => { '1' => '20' } );
691 $self->add_search_field_alias( 'keyword' => 'local-classification' => 'lcn' );
692 $self->add_search_field_alias( 'keyword' => 'local-classification' => 'callnum' );
693 $self->add_bib1_field_map('keyword' => 'bib-level' => 'biblioserver' => { '1' => '1021' } );
694 $self->add_bib1_field_map('keyword' => 'code-institution' => 'biblioserver' => { '1' => '56' } );
695 $self->add_bib1_field_map('keyword' => 'language' => 'biblioserver' => { '1' => '54' } );
696 $self->add_search_field_alias( 'keyword' => 'language' => 'ln' );
697 $self->add_bib1_field_map('keyword' => 'record-type' => 'biblioserver' => { '1' => '1001' } );
698 $self->add_search_field_alias( 'keyword' => 'record-type' => 'rtype' );
699 $self->add_search_field_alias( 'keyword' => 'record-type' => 'mc-rtype' );
700 $self->add_search_field_alias( 'keyword' => 'record-type' => 'mus' );
701 $self->add_bib1_field_map('keyword' => 'content-type' => 'biblioserver' => { '1' => '1034' } );
702 $self->add_search_field_alias( 'keyword' => 'content-type' => 'ctype' );
703 $self->add_bib1_field_map('keyword' => 'lc-card-number' => 'biblioserver' => { '1' => '9' } );
704 $self->add_search_field_alias( 'keyword' => 'lc-card-number' => 'lc-card' );
705 $self->add_bib1_field_map('keyword' => 'local-number' => 'biblioserver' => { '1' => '12' } );
706 $self->add_search_field_alias( 'keyword' => 'local-number' => 'sn' );
707 $self->add_bib1_filter_map( 'biblioserver', 'copydate', { 'target_syntax_callback' => \&Koha::QueryParser::Driver::PQF::date_filter_target_callback, '1' => '30', '4' => '4' });
708 $self->add_bib1_filter_map( 'biblioserver', 'pubdate', { 'target_syntax_callback' => \&Koha::QueryParser::Driver::PQF::date_filter_target_callback, '1' => 'pubdate', '4' => '4' });
709 $self->add_bib1_filter_map( 'biblioserver', 'acqdate', { 'target_syntax_callback' => \&Koha::QueryParser::Driver::PQF::date_filter_target_callback, '1' => 'Date-of-acquisition', '4' => '4' });
710 $self->add_bib1_field_map('keyword' => 'isbn' => 'biblioserver' => { '1' => '7' } );
711 $self->add_search_field_alias( 'keyword' => 'isbn' => 'nb' );
712 $self->add_bib1_field_map('keyword' => 'issn' => 'biblioserver' => { '1' => '8' } );
713 $self->add_search_field_alias( 'keyword' => 'issn' => 'ns' );
714 $self->add_bib1_field_map('keyword' => 'identifier-standard' => 'biblioserver' => { '1' => '1007' } );
715 $self->add_search_field_alias( 'keyword' => 'identifier-standard' => 'ident' );
716 $self->add_bib1_field_map('keyword' => 'upc' => 'biblioserver' => { '1' => 'UPC' } );
717 $self->add_search_field_alias( 'keyword' => 'upc' => 'upc' );
718 $self->add_bib1_field_map('keyword' => 'ean' => 'biblioserver' => { '1' => 'EAN' } );
719 $self->add_search_field_alias( 'keyword' => 'ean' => 'ean' );
720 $self->add_bib1_field_map('keyword' => 'music' => 'biblioserver' => { '1' => 'Music-number' } );
721 $self->add_search_field_alias( 'keyword' => 'music' => 'music' );
722 $self->add_bib1_field_map('keyword' => 'stock-number' => 'biblioserver' => { '1' => '1028' } );
723 $self->add_search_field_alias( 'keyword' => 'stock-number' => 'stock-number' );
724 $self->add_bib1_field_map('keyword' => 'material-type' => 'biblioserver' => { '1' => '1031' } );
725 $self->add_search_field_alias( 'keyword' => 'material-type' => 'material-type' );
726 $self->add_bib1_field_map('keyword' => 'place-publication' => 'biblioserver' => { '1' => '59' } );
727 $self->add_search_field_alias( 'keyword' => 'place-publication' => 'pl' );
728 $self->add_bib1_field_map('keyword' => 'personal-name' => 'biblioserver' => { '1' => 'Personal-name' } );
729 $self->add_search_field_alias( 'keyword' => 'personal-name' => 'pn' );
730 $self->add_bib1_field_map('keyword' => 'publisher' => 'biblioserver' => { '1' => '1018' } );
731 $self->add_search_field_alias( 'keyword' => 'publisher' => 'pb' );
732 $self->add_bib1_field_map('keyword' => 'note' => 'biblioserver' => { '1' => '63' } );
733 $self->add_search_field_alias( 'keyword' => 'note' => 'nt' );
734 $self->add_bib1_field_map('keyword' => 'record-control-number' => 'biblioserver' => { '1' => '1045' } );
735 $self->add_search_field_alias( 'keyword' => 'record-control-number' => 'rcn' );
736 $self->add_bib1_field_map('subject' => '' => 'biblioserver' => { '1' => '21' } );
737 $self->add_search_field_alias( 'subject' => '' => 'su' );
738 $self->add_search_field_alias( 'subject' => '' => 'su-to' );
739 $self->add_search_field_alias( 'subject' => '' => 'su-geo' );
740 $self->add_search_field_alias( 'subject' => '' => 'su-ut' );
741 $self->add_bib1_field_map('subject' => 'name-personal' => 'biblioserver' => { '1' => '1009' } );
742 $self->add_search_field_alias( 'subject' => 'name-personal' => 'su-na' );
743 $self->add_bib1_field_map('title' => '' => 'biblioserver' => { '1' => '4' } );
744 $self->add_search_field_alias( 'title' => '' => 'ti' );
745 $self->add_bib1_field_map('title' => 'cover' => 'biblioserver' => { '1' => '36' } );
746 $self->add_search_field_alias( 'title' => 'cover' => 'title-cover' );
747 $self->add_bib1_field_map('keyword' => 'host-item' => 'biblioserver' => { '1' => '1033' } );
748 $self->add_bib1_field_map('keyword' => 'video-mt' => 'biblioserver' => { '1' => 'Video-mt' } );
749 $self->add_bib1_field_map('keyword' => 'graphics-type' => 'biblioserver' => { '1' => 'Graphic-type' } );
750 $self->add_bib1_field_map('keyword' => 'graphics-support' => 'biblioserver' => { '1' => 'Graphic-support' } );
751 $self->add_bib1_field_map('keyword' => 'type-of-serial' => 'biblioserver' => { '1' => 'Type-Of-Serial' } );
752 $self->add_bib1_field_map('keyword' => 'regularity-code' => 'biblioserver' => { '1' => 'Regularity-code' } );
753 $self->add_bib1_field_map('keyword' => 'material-type' => 'biblioserver' => { '1' => 'Material-type' } );
754 $self->add_bib1_field_map('keyword' => 'literature-code' => 'biblioserver' => { '1' => 'Literature-Code' } );
755 $self->add_bib1_field_map('keyword' => 'biography-code' => 'biblioserver' => { '1' => 'Biography-code' } );
756 $self->add_bib1_field_map('keyword' => 'illustration-code' => 'biblioserver' => { '1' => 'Illustration-code' } );
757 $self->add_bib1_field_map('title' => 'series' => 'biblioserver' => { '1' => '5' } );
758 $self->add_search_field_alias( 'title' => 'series' => 'title-series' );
759 $self->add_search_field_alias( 'title' => 'series' => 'se' );
760 $self->add_bib1_field_map('title' => 'uniform' => 'biblioserver' => { '1' => 'Title-uniform' } );
761 $self->add_search_field_alias( 'title' => 'uniform' => 'title-uniform' );
762 $self->add_bib1_field_map('subject' => 'authority-number' => 'biblioserver' => { '1' => 'Koha-Auth-Number' } );
763 $self->add_search_field_alias( 'subject' => 'authority-number' => 'an' );
764 $self->add_bib1_field_map('keyword' => 'control-number' => 'biblioserver' => { '1' => '9001' } );
765 $self->add_bib1_field_map('keyword' => 'biblionumber' => 'biblioserver' => { '1' => '9002', '5' => '100' } );
766 $self->add_bib1_field_map('keyword' => 'totalissues' => 'biblioserver' => { '1' => '9003' } );
767 $self->add_bib1_field_map('keyword' => 'cn-bib-source' => 'biblioserver' => { '1' => '9004' } );
768 $self->add_bib1_field_map('keyword' => 'cn-bib-sort' => 'biblioserver' => { '1' => '9005' } );
769 $self->add_bib1_field_map('keyword' => 'itemtype' => 'biblioserver' => { '1' => '9006' } );
770 $self->add_search_field_alias( 'keyword' => 'itemtype' => 'mc-itemtype' );
771 $self->add_bib1_field_map('keyword' => 'cn-class' => 'biblioserver' => { '1' => '9007' } );
772 $self->add_bib1_field_map('keyword' => 'cn-item' => 'biblioserver' => { '1' => '9008' } );
773 $self->add_bib1_field_map('keyword' => 'cn-prefix' => 'biblioserver' => { '1' => '9009' } );
774 $self->add_bib1_field_map('keyword' => 'cn-suffix' => 'biblioserver' => { '1' => '9010' } );
775 $self->add_bib1_field_map('keyword' => 'suppress' => 'biblioserver' => { '1' => '9011' } );
776 $self->add_bib1_field_map('keyword' => 'id-other' => 'biblioserver' => { '1' => '9012' } );
777 $self->add_bib1_field_map('keyword' => 'date-entered-on-file' => 'biblioserver' => { '1' => 'date-entered-on-file' } );
778 $self->add_bib1_field_map('keyword' => 'extent' => 'biblioserver' => { '1' => 'Extent' } );
779 $self->add_bib1_field_map('keyword' => 'llength' => 'biblioserver' => { '1' => 'llength' } );
780 $self->add_bib1_field_map('keyword' => 'summary' => 'biblioserver' => { '1' => 'Summary' } );
781 $self->add_bib1_field_map('keyword' => 'withdrawn' => 'biblioserver' => { '1' => '8001' } );
782 $self->add_bib1_field_map('keyword' => 'lost' => 'biblioserver' => { '1' => '8002' } );
783 $self->add_bib1_field_map('keyword' => 'classification-source' => 'biblioserver' => { '1' => '8003' } );
784 $self->add_bib1_field_map('keyword' => 'materials-specified' => 'biblioserver' => { '1' => '8004' } );
785 $self->add_bib1_field_map('keyword' => 'damaged' => 'biblioserver' => { '1' => '8005' } );
786 $self->add_bib1_field_map('keyword' => 'restricted' => 'biblioserver' => { '1' => '8006' } );
787 $self->add_bib1_field_map('keyword' => 'cn-sort' => 'biblioserver' => { '1' => '8007' } );
788 $self->add_bib1_field_map('keyword' => 'notforloan' => 'biblioserver' => { '1' => '8008', '4' => '109' } );
789 $self->add_bib1_field_map('keyword' => 'ccode' => 'biblioserver' => { '1' => '8009' } );
790 $self->add_search_field_alias( 'keyword' => 'ccode' => 'mc-ccode' );
791 $self->add_bib1_field_map('keyword' => 'itemnumber' => 'biblioserver' => { '1' => '8010' } );
792 $self->add_bib1_field_map('keyword' => 'homebranch' => 'biblioserver' => { '1' => 'homebranch' } );
793 $self->add_search_field_alias( 'keyword' => 'homebranch' => 'branch' );
794 $self->add_bib1_field_map('keyword' => 'holdingbranch' => 'biblioserver' => { '1' => '8012' } );
795 $self->add_bib1_field_map('keyword' => 'location' => 'biblioserver' => { '1' => '8013' } );
796 $self->add_search_field_alias( 'keyword' => 'location' => 'mc-loc' );
797 $self->add_bib1_field_map('keyword' => 'acqsource' => 'biblioserver' => { '1' => '8015' } );
798 $self->add_bib1_field_map('keyword' => 'coded-location-qualifier' => 'biblioserver' => { '1' => '8016' } );
799 $self->add_bib1_field_map('keyword' => 'price' => 'biblioserver' => { '1' => '8017' } );
800 $self->add_bib1_field_map('keyword' => 'stocknumber' => 'biblioserver' => { '1' => '1062' } );
801 $self->add_search_field_alias( 'keyword' => 'stocknumber' => 'inv' );
802 $self->add_bib1_field_map('keyword' => 'stack' => 'biblioserver' => { '1' => '8018' } );
803 $self->add_bib1_field_map('keyword' => 'issues' => 'biblioserver' => { '1' => '8019' } );
804 $self->add_bib1_field_map('keyword' => 'renewals' => 'biblioserver' => { '1' => '8020' } );
805 $self->add_bib1_field_map('keyword' => 'reserves' => 'biblioserver' => { '1' => '8021' } );
806 $self->add_bib1_field_map('keyword' => 'local-classification' => 'biblioserver' => { '1' => '8022' } );
807 $self->add_bib1_field_map('keyword' => 'barcode' => 'biblioserver' => { '1' => '8023' } );
808 $self->add_search_field_alias( 'keyword' => 'barcode' => 'bc' );
809 $self->add_bib1_field_map('keyword' => 'onloan' => 'biblioserver' => { '1' => '8024' } );
810 $self->add_bib1_field_map('keyword' => 'datelastseen' => 'biblioserver' => { '1' => '8025' } );
811 $self->add_bib1_field_map('keyword' => 'datelastborrowed' => 'biblioserver' => { '1' => '8026' } );
812 $self->add_bib1_field_map('keyword' => 'copynumber' => 'biblioserver' => { '1' => '8027' } );
813 $self->add_bib1_field_map('keyword' => 'uri' => 'biblioserver' => { '1' => '8028' } );
814 $self->add_bib1_field_map('keyword' => 'replacementprice' => 'biblioserver' => { '1' => '8029' } );
815 $self->add_bib1_field_map('keyword' => 'replacementpricedate' => 'biblioserver' => { '1' => '8030' } );
816 $self->add_bib1_field_map('keyword' => 'itype' => 'biblioserver' => { '1' => '8031' } );
817 $self->add_search_field_alias( 'keyword' => 'itype' => 'mc-itype' );
818 $self->add_bib1_field_map('keyword' => 'ff8-22' => 'biblioserver' => { '1' => '8822' } );
819 $self->add_bib1_field_map('keyword' => 'ff8-23' => 'biblioserver' => { '1' => '8823' } );
820 $self->add_bib1_field_map('keyword' => 'ff8-34' => 'biblioserver' => { '1' => '8834' } );
822 $self->add_bib1_field_map('keyword' => 'audience' => 'biblioserver' => { '1' => '8822' } );
823 $self->add_search_field_alias( 'keyword' => 'audience' => 'aud' );
825 # Content and Literary form
826 $self->add_bib1_field_map('keyword' => 'fiction' => 'biblioserver' => { '1' => '8833' } );
827 $self->add_search_field_alias( 'keyword' => 'fiction' => 'fic' );
828 $self->add_bib1_field_map('keyword' => 'biography' => 'biblioserver' => { '1' => '8834' } );
829 $self->add_search_field_alias( 'keyword' => 'biography' => 'bio' );
832 $self->add_bib1_field_map('keyword' => 'format' => 'biblioserver' => { '1' => '8823' } );
833 # format used as a limit FIXME: needed?
834 $self->add_bib1_field_map('keyword' => 'l-format' => 'biblioserver' => { '1' => '8703' } );
836 $self->add_bib1_field_map('keyword' => 'illustration-code' => 'biblioserver' => { '1' => 'Illustration-code ' } );
839 $self->add_bib1_field_map('keyword' => 'lex' => 'biblioserver' => { '1' => '9903 r=r' } );
841 #Accelerated Reader Level
842 $self->add_bib1_field_map('keyword' => 'arl' => 'biblioserver' => { '1' => '9904 r=r' } );
844 #Accelerated Reader Point
845 $self->add_bib1_field_map('keyword' => 'arp' => 'biblioserver' => { '1' => '9013 r=r' } );
848 $self->add_bib1_field_map('keyword' => 'curriculum' => 'biblioserver' => { '1' => '9658' } );
851 $self->add_bib1_field_map('keyword' => 'popularity' => 'biblioserver' => { '1' => 'issues' } );
854 $self->add_bib1_field_map('keyword' => 'dt-bks' => 'biblioserver' => { '1' => '8700' } );
855 $self->add_bib1_field_map('keyword' => 'dt-vis' => 'biblioserver' => { '1' => '8700' } );
856 $self->add_bib1_field_map('keyword' => 'dt-sr' => 'biblioserver' => { '1' => '8700' } );
857 $self->add_bib1_field_map('keyword' => 'dt-cf' => 'biblioserver' => { '1' => '8700' } );
858 $self->add_bib1_field_map('keyword' => 'dt-map' => 'biblioserver' => { '1' => '8700' } );
860 $self->add_bib1_field_map('keyword' => 'name' => 'biblioserver' => { '1' => '1002' } );
861 $self->add_bib1_field_map('keyword' => 'item' => 'biblioserver' => { '1' => '9520' } );
862 $self->add_bib1_field_map('keyword' => 'host-item-number' => 'biblioserver' => { '1' => '8911' } );
863 $self->add_search_field_alias( 'keyword' => 'host-item-number' => 'hi' );
865 $self->add_bib1_field_map('keyword' => 'alwaysmatch' => 'biblioserver' => { '1' => '_ALLRECORDS', '2' => '103' } );
866 $self->add_bib1_field_map('subject' => 'complete' => 'biblioserver' => { '1' => '21', '3' => '1', '4' => '1', '5' => '100', '6' => '3' } );
868 $self->add_bib1_modifier_map('relevance' => 'biblioserver' => { '2' => '102' } );
869 $self->add_bib1_modifier_map('title-sort-za' => 'biblioserver' => { '7' => '2', '1' => '36', '' => '0', 'op' => '@or' } );
870 $self->add_bib1_modifier_map('title-sort-az' => 'biblioserver' => { '7' => '1', '1' => '36', '' => '0', 'op' => '@or' } );
871 $self->add_bib1_modifier_map('relevance_dsc' => 'biblioserver' => { '2' => '102' } );
872 $self->add_bib1_modifier_map('title_dsc' => 'biblioserver' => { '7' => '2', '1' => '4', '' => '0', 'op' => '@or' } );
873 $self->add_bib1_modifier_map('title_asc' => 'biblioserver' => { '7' => '1', '1' => '4', '' => '0', 'op' => '@or' } );
874 $self->add_bib1_modifier_map('author_asc' => 'biblioserver' => { '7' => '2', '1' => '1003', '' => '0', 'op' => '@or' } );
875 $self->add_bib1_modifier_map('author_dsc' => 'biblioserver' => { '7' => '1', '1' => '1003', '' => '0', 'op' => '@or' } );
876 $self->add_bib1_modifier_map('popularity_asc' => 'biblioserver' => { '7' => '2', '1' => '9003', '' => '0', 'op' => '@or' } );
877 $self->add_bib1_modifier_map('popularity_dsc' => 'biblioserver' => { '7' => '1', '1' => '9003', '' => '0', 'op' => '@or' } );
878 $self->add_bib1_modifier_map('call_number_asc' => 'biblioserver' => { '7' => '2', '1' => '8007', '' => '0', 'op' => '@or' } );
879 $self->add_bib1_modifier_map('call_number_dsc' => 'biblioserver' => { '7' => '1', '1' => '8007', '' => '0', 'op' => '@or' } );
880 $self->add_bib1_modifier_map('pubdate_asc' => 'biblioserver' => { '7' => '2', '1' => '31', '' => '0', 'op' => '@or' } );
881 $self->add_bib1_modifier_map('pubdate_dsc' => 'biblioserver' => { '7' => '1', '1' => '31', '' => '0', 'op' => '@or' } );
882 $self->add_bib1_modifier_map('acqdate_asc' => 'biblioserver' => { '7' => '2', '1' => '32', '' => '0', 'op' => '@or' } );
883 $self->add_bib1_modifier_map('acqdate_dsc' => 'biblioserver' => { '7' => '1', '1' => '32', '' => '0', 'op' => '@or' } );
885 $self->add_bib1_modifier_map('title_za' => 'biblioserver' => { '7' => '2', '1' => '4', '' => '0', 'op' => '@or' } );
886 $self->add_bib1_modifier_map('title_az' => 'biblioserver' => { '7' => '1', '1' => '4', '' => '0', 'op' => '@or' } );
887 $self->add_bib1_modifier_map('author_za' => 'biblioserver' => { '7' => '2', '1' => '1003', '' => '0', 'op' => '@or' } );
888 $self->add_bib1_modifier_map('author_az' => 'biblioserver' => { '7' => '1', '1' => '1003', '' => '0', 'op' => '@or' } );
889 $self->add_bib1_modifier_map('ascending' => 'biblioserver' => { '7' => '1' } );
890 $self->add_bib1_modifier_map('descending' => 'biblioserver' => { '7' => '2' } );
892 $self->add_bib1_field_map('title' => 'exacttitle' => 'biblioserver' => { '1' => '4', '4' => '1', '6' => '3' } );
893 $self->add_search_field_alias( 'title' => 'exacttitle' => 'ti,ext' );
894 $self->add_bib1_field_map('author' => 'exactauthor' => 'biblioserver' => { '1' => '1003', '4' => '1', '6' => '3' } );
895 $self->add_search_field_alias( 'author' => 'exactauthor' => 'au,ext' );
897 $self->add_bib1_field_map('subject' => 'headingmain' => 'authorityserver' => { '1' => 'Heading-Main' } );
898 $self->add_bib1_field_map('subject' => 'heading' => 'authorityserver' => { '1' => 'Heading' } );
899 $self->add_bib1_field_map('subject' => 'matchheading' => 'authorityserver' => { '1' => 'Match-heading' } );
900 $self->add_bib1_field_map('subject' => 'seefrom' => 'authorityserver' => { '1' => 'Match-heading-see-from' } );
901 $self->add_bib1_field_map('subject' => '' => 'authorityserver' => { '1' => 'Match-heading' } );
902 $self->add_bib1_field_map('keyword' => 'alwaysmatch' => 'authorityserver' => { '1' => '_ALLRECORDS', '2' => '103' } );
903 $self->add_bib1_field_map('keyword' => 'match' => 'authorityserver' => { '1' => 'Match' } );
904 $self->add_bib1_field_map('keyword' => 'thesaurus' => 'authorityserver' => { '1' => 'Subject-heading-thesaurus' } );
905 $self->add_bib1_field_map('keyword' => 'authtype' => 'authorityserver' => { '1' => 'authtype', '5' => '100' } );
906 $self->add_bib1_field_map('keyword' => '' => 'authorityserver' => { '1' => 'Any' } );
907 $self->add_search_field_alias( 'subject' => 'headingmain' => 'mainmainentry' );
908 $self->add_search_field_alias( 'subject' => 'heading' => 'mainentry' );
909 $self->add_search_field_alias( 'subject' => 'heading' => 'he' );
910 $self->add_search_field_alias( 'subject' => 'matchheading' => 'match-heading' );
911 $self->add_search_field_alias( 'keyword' => '' => 'any' );
912 $self->add_search_field_alias( 'keyword' => 'match' => 'match' );
913 $self->add_search_field_alias( 'subject' => 'seefrom' => 'see-from' );
914 $self->add_search_field_alias( 'keyword' => 'thesaurus' => 'thesaurus' );
915 $self->add_search_field_alias( 'keyword' => 'alwaysmatch' => 'all' );
916 $self->add_search_field_alias( 'keyword' => 'authtype' => 'authtype' );
917 $self->add_search_field_alias( 'keyword' => 'authtype' => 'at' );
919 $self->add_bib1_field_map('subject' => 'start' => 'authorityserver' => { '3' => '2', '4' => '1', '5' => '1' } );
920 $self->add_bib1_field_map('subject' => 'exact' => 'authorityserver' => { '4' => '1', '5' => '100', '6' => '3' } );
922 $self->add_bib1_modifier_map('HeadingAsc' => 'authorityserver' => { '7' => '1', '1' => 'Heading', '' => '0', 'op' => '@or' } );
923 $self->add_bib1_modifier_map('HeadingDsc' => 'authorityserver' => { '7' => '2', '1' => 'Heading', '' => '0', 'op' => '@or' } );
924 $self->add_bib1_modifier_map('AuthidAsc' => 'authorityserver' => { '7' => '1', '1' => 'Local-Number', '' => '0', 'op' => '@or' } );
925 $self->add_bib1_modifier_map('AuthidDsc' => 'authorityserver' => { '7' => '2', '1' => 'Local-Number', '' => '0', 'op' => '@or' } );
926 $self->add_bib1_modifier_map('Relevance' => 'authorityserver' => { '2' => '102' } );