1 package Koha::QueryParser::Driver::PQF;
2 use base qw(OpenILS::QueryParser Class::Accessor);
7 use Module::Load::Conditional qw(can_load);
8 use Koha::QueryParser::Driver::PQF::Util;
9 use Koha::QueryParser::Driver::PQF::query_plan;
10 use Koha::QueryParser::Driver::PQF::query_plan::facet;
11 use Koha::QueryParser::Driver::PQF::query_plan::filter;
12 use Koha::QueryParser::Driver::PQF::query_plan::modifier;
13 use Koha::QueryParser::Driver::PQF::query_plan::node;
14 use Koha::QueryParser::Driver::PQF::query_plan::node::atom;
15 use Koha::QueryParser::Driver::PQF::query_plan::node::atom;
20 Koha::QueryParser::Driver::PQF - QueryParser driver for PQF
24 use Koha::QueryParser::Driver::PQF;
25 my $QParser = Koha::QueryParser::Driver::PQF->new(%args);
29 Main entrypoint into the QueryParser PQF driver. PQF is the Prefix Query
30 Language, the syntax used to serialize Z39.50 queries.
34 In order to simplify Bib-1 attribute mapping, this driver uses Class::Accessor
35 for accessing the following maps:
39 =item B<bib1_field_map> - search class/field Bib-1 mappings
41 =item B<bib1_modifier_map> - search modifier mappings
43 =item B<bib1_filter_map> - search filter mappings
45 =item B<bib1_relevance_bump_map> - relevance bump mappings
51 __PACKAGE__->mk_accessors(qw(bib1_field_map bib1_modifier_map bib1_filter_map bib1_relevance_bump_map));
59 Overridden accessor method for Class::Accessor. (Do not call directly)
65 return $self->_map(@_);
70 Overridden mutator method for Class::Accessor. (Do not call directly)
76 return $self->_map(@_);
79 =head2 add_bib1_field_map
81 $QParser->add_bib1_field_map($class => $field => $server => \%attributes);
83 $QParser->add_bib1_field_map('author' => 'personal' => 'biblioserver' =>
86 Adds a search field<->bib1 attribute mapping for the specified server. The
87 %attributes hash contains maps Bib-1 Attributes to the appropropriate
88 values. Not all attributes must be specified.
92 sub add_bib1_field_map {
93 my ($self, $class, $field, $server, $attributes) = @_;
95 $self->add_search_field( $class => $field );
96 $self->add_search_field_alias( $class => $field => $field );
97 return $self->_add_field_mapping($self->bib1_field_map, $class, $field, $server, $attributes);
100 =head2 add_bib1_modifier_map
102 $QParser->add_bib1_modifier_map($name => $server => \%attributes);
104 $QParser->add_bib1_modifier_map('ascending' => 'biblioserver' =>
107 Adds a search modifier<->bib1 attribute mapping for the specified server. The
108 %attributes hash contains maps Bib-1 Attributes to the appropropriate
109 values. Not all attributes must be specified.
113 sub add_bib1_modifier_map {
114 my ($self, $name, $server, $attributes) = @_;
116 $self->add_search_modifier( $name );
118 return $self->_add_mapping($self->bib1_modifier_map, $name, $server, $attributes);
121 =head2 add_bib1_filter_map
123 $QParser->add_bib1_filter_map($name => $server => \%attributes);
125 $QParser->add_bib1_filter_map('date' => 'biblioserver' =>
126 { 'callback' => &_my_callback });
128 Adds a search filter<->bib1 attribute mapping for the specified server. The
129 %attributes hash maps Bib-1 Attributes to the appropropriate values and
130 provides a callback for the filter. Not all attributes must be specified.
134 sub add_bib1_filter_map {
135 my ($self, $name, $server, $attributes) = @_;
137 $self->add_search_filter( $name, $attributes->{'callback'} );
139 return $self->_add_mapping($self->bib1_filter_map, $name, $server, $attributes);
142 =head2 add_relevance_bump
144 $QParser->add_relevance_bump($class, $field, $server, $multiplier, $active);
145 $QParser->add_relevance_bump('title' => 'exact' => 'biblioserver' => 34, 1);
147 Add a relevance bump to the specified field. When searching for a class without
148 any fields, all the relevance bumps for the specified class will be 'OR'ed
153 sub add_relevance_bump {
154 my ($self, $class, $field, $server, $multiplier, $active) = @_;
155 my $attributes = { '9' => $multiplier, '2' => '102', 'active' => $active };
157 $self->add_search_field( $class => $field );
158 return $self->_add_field_mapping($self->bib1_relevance_bump_map, $class, $field, $server, $attributes);
164 my $pqf = $QParser->target_syntax($server, [$query]);
165 my $pqf = $QParser->target_syntax('biblioserver', 'author|personal:smith');
166 print $pqf; # assuming all the indexes are configured,
167 # prints '@attr 1=1003 @attr 4=6 "smith"'
169 Transforms the current or specified query into a PQF query string for the
175 my ($self, $server, $query) = @_;
177 $self->parse($query) if $query;
178 warn "QP query for $server: " . $self->query . "\n" if $self->debug;
179 $pqf = $self->parse_tree->target_syntax($server);
180 warn "PQF query: $pqf\n" if $self->debug;
187 =head2 date_filter_target_callback
189 $QParser->add_bib1_filter_map($server, { 'target_syntax_callback' => \&Koha::QueryParser::Driver::PQF::date_filter_target_callback, '1' => 'pubdate' });
191 Callback for date filters. Note that although the first argument is the QParser
192 object, this is technically not an object-oriented routine. This has no
193 real-world implications.
197 sub date_filter_target_callback {
198 my ($QParser, $filter, $params, $negate, $server) = @_;
199 my $attr_string = $QParser->bib1_mapping_by_name( 'filter', $filter, $server )->{'attr_string'};
201 foreach my $datespec (@$params) {
204 if ($datespec =~ m/(.*)-(.*)/) {
206 $datepqf .= $attr_string . ' @attr 2=4 "' . $1 . '"';
209 $datepqf .= $attr_string . ' @attr 2=2 "' . $2 . '"';
210 $datepqf = ' @and ' . $datepqf if $1;
213 $datepqf .= $attr_string . ' "' . $datespec . '"';
216 $pqf = ' @or ' . ($negate ? '@not @attr 1=_ALLRECORDS @attr 2=103 "" ' : '') . $pqf if $pqf;
224 return $self->_map('bib1_field_map', $map);
226 Retrieves or sets a map.
231 my ($self, $name, $map) = @_;
232 $self->custom_data->{$name} ||= {};
233 $self->custom_data->{$name} = $map if ($map);
234 return $self->custom_data->{$name};
239 return $self->_add_mapping($map, $name, $server, $attributes)
241 Adds a mapping. Note that this is not used for mappings relating to fields.
246 my ($self, $map, $name, $server, $attributes) = @_;
248 my $attr_string = Koha::QueryParser::Driver::PQF::Util::attributes_to_attr_string($attributes);
249 $attributes->{'attr_string'} = $attr_string;
251 $map->{'by_name'}{$name}{$server} = $attributes;
252 $map->{'by_attr'}{$server}{$attr_string} = { 'name' => $name, %$attributes };
257 =head2 _add_field_mapping
259 return $self->_add_field_mapping($map, $class, $field, $server, $attributes)
261 Adds a mapping for field-related data.
265 sub _add_field_mapping {
266 my ($self, $map, $class, $field, $server, $attributes) = @_;
267 my $attr_string = Koha::QueryParser::Driver::PQF::Util::attributes_to_attr_string($attributes);
268 $attributes->{'attr_string'} = $attr_string;
270 $map->{'by_name'}{$class}{$field}{$server} = $attributes;
271 $map->{'by_attr'}{$server}{$attr_string} = { 'classname' => $class, 'field' => $field, %$attributes };
276 =head2 bib1_mapping_by_name
278 my $attributes = $QParser->bib1_mapping_by_name($type, $name[, $subname], $server);
279 my $attributes = $QParser->bib1_mapping_by_name('field', 'author', 'personal', 'biblioserver');
280 my $attributes = $QParser->bib1_mapping_by_name('filter', 'pubdate', 'biblioserver');
282 Retrieve the Bib-1 attribute set associated with the specified mapping.
285 sub bib1_mapping_by_name {
287 my ($self, $type, $name, $field) = @_;
289 return unless ($server && $name);
290 return unless ($type eq 'field' || $type eq 'modifier' || $type eq 'filter' || $type eq 'relevance_bump');
291 if ($type eq 'field' || $type eq 'relevance_bump') {
292 # Unfortunately field is a special case thanks to the class->field hierarchy
293 return $self->_map('bib1_' . $type . '_map')->{'by_name'}{$name}{$field}{$server} if $field;
294 return $self->_map('bib1_' . $type . '_map')->{'by_name'}{$name};
296 return $self->_map('bib1_' . $type . '_map')->{'by_name'}{$name}{$server};
300 =head2 bib1_mapping_by_attr
302 my $field = $QParser->bib1_mapping_by_attr($type, $server, \%attr);
303 my $field = $QParser->bib1_mapping_by_attr('field', 'biblioserver', {'1' => '1004'});
304 print $field->{'classname'}; # prints "author"
305 print $field->{'field'}; # prints "personal"
307 Retrieve the search field/modifier/filter used for the specified Bib-1 attribute set.
311 sub bib1_mapping_by_attr {
312 my ($self, $type, $server, $attributes) = @_;
313 return unless ($server && $attributes);
315 my $attr_string = Koha::QueryParser::Driver::PQF::Util::attributes_to_attr_string($attributes);
317 return $self->bib1_mapping_by_attr_string($type, $server, $attr_string);
320 =head2 bib1_mapping_by_attr_string
322 my $field = $QParser->bib1_mapping_by_attr_string($type, $server, $attr_string);
323 my $field = $QParser->bib1_mapping_by_attr_string('field', 'biblioserver', '@attr 1=1004');
324 print $field->{'classname'}; # prints "author"
325 print $field->{'field'}; # prints "personal"
327 Retrieve the search field/modifier/filter used for the specified Bib-1 attribute string
332 sub bib1_mapping_by_attr_string {
333 my ($self, $type, $server, $attr_string) = @_;
334 return unless ($server && $attr_string);
335 return unless ($type eq 'field' || $type eq 'modifier' || $type eq 'filter' || $type eq 'relevance_bump');
337 return $self->_map('bib1_' . $type . '_map')->{'by_attr'}{$server}{$attr_string};
340 =head2 clear_all_configuration
342 $QParser->clear_all_configuration
344 Clear all configuration. This is a highly destructive method. You may
349 sub clear_all_configuration {
351 %OpenILS::QueryParser::parser_config = (
352 'OpenILS::QueryParser' => {
372 =head2 clear_all_mappings
374 $QParser->clear_all_mappings
376 Clear all bib-1 mappings.
380 sub clear_all_mappings {
383 foreach my $name (qw(field modifier filter relevance_bump)) {
384 $self->custom_data->{'bib1_' . $name . '_map'} = { };
390 =head2 _canonicalize_field_map
392 Convert a field map into its canonical form for serialization. Used only for
393 fields and relevance bumps.
397 sub _canonicalize_field_map {
398 my ( $map, $aliases ) = @_;
399 my $canonical_map = {};
401 foreach my $class ( keys %{ $map->{'by_name'} } ) {
402 $canonical_map->{$class} ||= {};
403 foreach my $field ( keys %{ $map->{'by_name'}->{$class} } ) {
406 'label' => ucfirst($field),
410 my $server ( keys %{ $map->{'by_name'}->{$class}->{$field} } )
412 $field_map->{'bib1_mapping'} ||= {};
413 $field_map->{'bib1_mapping'}->{$server} =
414 $map->{'by_name'}->{$class}->{$field}->{$server};
415 delete $field_map->{'bib1_mapping'}->{$server}->{'attr_string'}
417 $field_map->{'bib1_mapping'}->{$server}
422 $field_map->{'aliases'} = [];
423 foreach my $alias ( @{ $aliases->{$class}->{$field} } ) {
424 push @{ $field_map->{'aliases'} },
428 $canonical_map->{$class}->{$field} = $field_map;
431 return $canonical_map;
434 =head2 _canonicalize_map
436 Convert a map into its canonical form for serialization. Not used for fields.
440 sub _canonicalize_map {
442 my $canonical_map = {};
444 foreach my $name ( keys %{ $map->{'by_name'} } ) {
445 $canonical_map->{$name} = {
446 'label' => ucfirst($name),
450 foreach my $server ( keys %{ $map->{'by_name'}->{$name} } ) {
451 $canonical_map->{$name}->{'bib1_mapping'}->{$server} =
452 $map->{'by_name'}->{$name}->{$server};
453 delete $canonical_map->{$name}->{'bib1_mapping'}->{$server}
456 $canonical_map->{$name}->{'bib1_mapping'}->{$server}
461 return $canonical_map;
464 =head2 serialize_mappings
466 my $yaml = $QParser->serialize_mappings;
467 my $json = $QParser->serialize_mappings('json');
469 Serialize Bib-1 mappings to YAML or JSON.
473 sub serialize_mappings {
474 my ( $self, $format ) = @_;
478 $config->{'field_mappings'} =
479 _canonicalize_field_map( $self->bib1_field_map,
480 $self->search_field_aliases );
481 $config->{'modifier_mappings'} =
482 _canonicalize_map( $self->bib1_modifier_map );
483 $config->{'filter_mappings'} = _canonicalize_map( $self->bib1_filter_map );
484 $config->{'relevance_bumps'} =
485 _canonicalize_field_map( $self->bib1_relevance_bump_map );
487 if ( $format eq 'json' && can_load( modules => { 'JSON' => undef } ) ) {
488 return JSON::to_json($config);
490 elsif ( can_load( modules => { 'YAML::Any' => undef } ) ) {
491 return YAML::Any::Dump($config);
498 $QParser->initialize( { 'bib1_field_mappings' => \%bib1_field_mappings,
499 'search_field_alias_mappings' => \%search_field_alias_mappings,
500 'bib1_modifier_mappings' => \%bib1_modifier_mappings,
501 'bib1_filter_mappings' => \%bib1_filter_mappings,
502 'relevance_bumps' => \%relevance_bumps });
504 Initialize the QueryParser mapping tables based on the provided configuration.
505 This method was written to play nice with YAML configuration files loaded by load_config.
510 my ( $self, $args ) = @_;
512 my $field_mappings = $args->{'field_mappings'};
513 my $modifier_mappings = $args->{'modifier_mappings'};
514 my $filter_mappings = $args->{'filter_mappings'};
515 my $relbumps = $args->{'relevance_bumps'};
516 my ( $server, $bib1_mapping );
517 foreach my $class ( keys %$field_mappings ) {
518 foreach my $field ( keys %{ $field_mappings->{$class} } ) {
519 if ( $field_mappings->{$class}->{$field}->{'enabled'} ) {
520 while ( ( $server, $bib1_mapping ) =
522 %{ $field_mappings->{$class}->{$field}->{'bib1_mapping'} } )
524 $self->add_bib1_field_map(
525 $class => $field => $server => $bib1_mapping );
527 $self->add_search_field_alias( $class => $field =>
528 $field_mappings->{$class}->{$field}->{'index'} );
530 @{ $field_mappings->{$class}->{$field}->{'aliases'} } )
534 $field_mappings->{$class}->{$field}->{'index'} );
535 $self->add_search_field_alias( $class => $field => $alias );
540 foreach my $modifier ( keys %$modifier_mappings ) {
541 if ( $modifier_mappings->{$modifier}->{'enabled'} ) {
542 while ( ( $server, $bib1_mapping ) =
543 each %{ $modifier_mappings->{$modifier}->{'bib1_mapping'} } )
545 $self->add_bib1_modifier_map(
546 $modifier => $server => $bib1_mapping );
550 foreach my $filter ( keys %$filter_mappings ) {
551 if ( $filter_mappings->{$filter}->{'enabled'} ) {
552 while ( ( $server, $bib1_mapping ) =
553 each %{ $filter_mappings->{$filter}->{'bib1_mapping'} } )
555 if ( $bib1_mapping->{'target_syntax_callback'} eq
556 'date_filter_target_callback' )
558 $bib1_mapping->{'target_syntax_callback'} =
559 \&Koha::QueryParser::Driver::PQF::date_filter_target_callback;
561 $self->add_bib1_filter_map(
562 $filter => $server => $bib1_mapping );
566 foreach my $class ( keys %$relbumps ) {
567 foreach my $field ( keys %{ $relbumps->{$class} } ) {
568 if ( $relbumps->{$class}->{$field}->{'enabled'} ) {
569 while ( ( $server, $bib1_mapping ) =
570 each %{ $relbumps->{$class}->{$field}->{'bib1_mapping'} } )
572 $self->add_relevance_bump(
573 $class => $field => $server => $bib1_mapping,
585 $QParser->load_config($file_name);
587 Load a YAML file with a parser configuration. The YAML file should match the following format:
615 1: Date-of-acquisition
617 target_syntax_callback: date_filter_target_callback
635 my ($self, $file) = @_;
637 return unless ($file && -f $file);
638 my $config = YAML::Any::LoadFile($file);
639 return unless ($config);
640 $self->initialize($config);
648 This routine initializes the QueryParser driver with a reasonable set of
649 defaults. This is intended only for testing. Although such test stubs are
650 generally not included in Koha, this type of test stub is used by other
651 QueryParser implementations, and it seems sensible to maintain consistency
659 $self->default_search_class( 'keyword' );
661 $self->add_bib1_field_map('keyword' => 'abstract' => 'biblioserver' => { '1' => '62' } );
662 $self->add_search_field_alias( 'keyword' => 'abstract' => 'ab' );
663 $self->add_bib1_field_map('keyword' => '' => 'biblioserver' => { '1' => '1016' } );
664 $self->add_search_field_alias( 'keyword' => '' => 'kw' );
665 $self->add_bib1_field_map('author' => '' => 'biblioserver' => { '1' => '1003' } );
666 $self->add_search_field_alias( 'author' => '' => 'au' );
667 $self->add_bib1_field_map('author' => 'personal' => 'biblioserver' => { '1' => '1004' } );
668 $self->add_bib1_field_map('author' => 'corporate' => 'biblioserver' => { '1' => '1005' } );
669 $self->add_search_field_alias( 'author' => 'corporate' => 'cpn' );
670 $self->add_bib1_field_map('author' => 'conference' => 'biblioserver' => { '1' => '1006' } );
671 $self->add_search_field_alias( 'author' => 'conference' => 'cfn' );
672 $self->add_bib1_field_map('keyword' => 'local-classification' => 'biblioserver' => { '1' => '20' } );
673 $self->add_search_field_alias( 'keyword' => 'local-classification' => 'lcn' );
674 $self->add_search_field_alias( 'keyword' => 'local-classification' => 'callnum' );
675 $self->add_bib1_field_map('keyword' => 'bib-level' => 'biblioserver' => { '1' => '1021' } );
676 $self->add_bib1_field_map('keyword' => 'code-institution' => 'biblioserver' => { '1' => '56' } );
677 $self->add_bib1_field_map('keyword' => 'language' => 'biblioserver' => { '1' => '54' } );
678 $self->add_search_field_alias( 'keyword' => 'language' => 'ln' );
679 $self->add_bib1_field_map('keyword' => 'record-type' => 'biblioserver' => { '1' => '1001' } );
680 $self->add_search_field_alias( 'keyword' => 'record-type' => 'rtype' );
681 $self->add_search_field_alias( 'keyword' => 'record-type' => 'mc-rtype' );
682 $self->add_search_field_alias( 'keyword' => 'record-type' => 'mus' );
683 $self->add_bib1_field_map('keyword' => 'content-type' => 'biblioserver' => { '1' => '1034' } );
684 $self->add_search_field_alias( 'keyword' => 'content-type' => 'ctype' );
685 $self->add_bib1_field_map('keyword' => 'lc-card-number' => 'biblioserver' => { '1' => '9' } );
686 $self->add_search_field_alias( 'keyword' => 'lc-card-number' => 'lc-card' );
687 $self->add_bib1_field_map('keyword' => 'local-number' => 'biblioserver' => { '1' => '12' } );
688 $self->add_search_field_alias( 'keyword' => 'local-number' => 'sn' );
689 $self->add_bib1_filter_map( 'biblioserver', 'copydate', { 'target_syntax_callback' => \&Koha::QueryParser::Driver::PQF::date_filter_target_callback, '1' => '30', '4' => '4' });
690 $self->add_bib1_filter_map( 'biblioserver', 'pubdate', { 'target_syntax_callback' => \&Koha::QueryParser::Driver::PQF::date_filter_target_callback, '1' => 'pubdate', '4' => '4' });
691 $self->add_bib1_filter_map( 'biblioserver', 'acqdate', { 'target_syntax_callback' => \&Koha::QueryParser::Driver::PQF::date_filter_target_callback, '1' => 'Date-of-acquisition', '4' => '4' });
692 $self->add_bib1_field_map('keyword' => 'isbn' => 'biblioserver' => { '1' => '7' } );
693 $self->add_search_field_alias( 'keyword' => 'isbn' => 'nb' );
694 $self->add_bib1_field_map('keyword' => 'issn' => 'biblioserver' => { '1' => '8' } );
695 $self->add_search_field_alias( 'keyword' => 'issn' => 'ns' );
696 $self->add_bib1_field_map('keyword' => 'identifier-standard' => 'biblioserver' => { '1' => '1007' } );
697 $self->add_search_field_alias( 'keyword' => 'identifier-standard' => 'ident' );
698 $self->add_bib1_field_map('keyword' => 'upc' => 'biblioserver' => { '1' => 'UPC' } );
699 $self->add_search_field_alias( 'keyword' => 'upc' => 'upc' );
700 $self->add_bib1_field_map('keyword' => 'ean' => 'biblioserver' => { '1' => 'EAN' } );
701 $self->add_search_field_alias( 'keyword' => 'ean' => 'ean' );
702 $self->add_bib1_field_map('keyword' => 'music' => 'biblioserver' => { '1' => 'Music-number' } );
703 $self->add_search_field_alias( 'keyword' => 'music' => 'music' );
704 $self->add_bib1_field_map('keyword' => 'stock-number' => 'biblioserver' => { '1' => '1028' } );
705 $self->add_search_field_alias( 'keyword' => 'stock-number' => 'stock-number' );
706 $self->add_bib1_field_map('keyword' => 'material-type' => 'biblioserver' => { '1' => '1031' } );
707 $self->add_search_field_alias( 'keyword' => 'material-type' => 'material-type' );
708 $self->add_bib1_field_map('keyword' => 'place-publication' => 'biblioserver' => { '1' => '59' } );
709 $self->add_search_field_alias( 'keyword' => 'place-publication' => 'pl' );
710 $self->add_bib1_field_map('keyword' => 'personal-name' => 'biblioserver' => { '1' => 'Personal-name' } );
711 $self->add_search_field_alias( 'keyword' => 'personal-name' => 'pn' );
712 $self->add_bib1_field_map('keyword' => 'publisher' => 'biblioserver' => { '1' => '1018' } );
713 $self->add_search_field_alias( 'keyword' => 'publisher' => 'pb' );
714 $self->add_bib1_field_map('keyword' => 'note' => 'biblioserver' => { '1' => '63' } );
715 $self->add_search_field_alias( 'keyword' => 'note' => 'nt' );
716 $self->add_bib1_field_map('keyword' => 'record-control-number' => 'biblioserver' => { '1' => '1045' } );
717 $self->add_search_field_alias( 'keyword' => 'record-control-number' => 'rcn' );
718 $self->add_bib1_field_map('subject' => '' => 'biblioserver' => { '1' => '21' } );
719 $self->add_search_field_alias( 'subject' => '' => 'su' );
720 $self->add_search_field_alias( 'subject' => '' => 'su-to' );
721 $self->add_search_field_alias( 'subject' => '' => 'su-geo' );
722 $self->add_search_field_alias( 'subject' => '' => 'su-ut' );
723 $self->add_bib1_field_map('subject' => 'name-personal' => 'biblioserver' => { '1' => '1009' } );
724 $self->add_search_field_alias( 'subject' => 'name-personal' => 'su-na' );
725 $self->add_bib1_field_map('title' => '' => 'biblioserver' => { '1' => '4' } );
726 $self->add_search_field_alias( 'title' => '' => 'ti' );
727 $self->add_bib1_field_map('title' => 'cover' => 'biblioserver' => { '1' => '36' } );
728 $self->add_search_field_alias( 'title' => 'cover' => 'title-cover' );
729 $self->add_bib1_field_map('keyword' => 'host-item' => 'biblioserver' => { '1' => '1033' } );
730 $self->add_bib1_field_map('keyword' => 'video-mt' => 'biblioserver' => { '1' => 'Video-mt' } );
731 $self->add_bib1_field_map('keyword' => 'graphics-type' => 'biblioserver' => { '1' => 'Graphic-type' } );
732 $self->add_bib1_field_map('keyword' => 'graphics-support' => 'biblioserver' => { '1' => 'Graphic-support' } );
733 $self->add_bib1_field_map('keyword' => 'type-of-serial' => 'biblioserver' => { '1' => 'Type-Of-Serial' } );
734 $self->add_bib1_field_map('keyword' => 'regularity-code' => 'biblioserver' => { '1' => 'Regularity-code' } );
735 $self->add_bib1_field_map('keyword' => 'material-type' => 'biblioserver' => { '1' => 'Material-type' } );
736 $self->add_bib1_field_map('keyword' => 'literature-code' => 'biblioserver' => { '1' => 'Literature-Code' } );
737 $self->add_bib1_field_map('keyword' => 'biography-code' => 'biblioserver' => { '1' => 'Biography-code' } );
738 $self->add_bib1_field_map('keyword' => 'illustration-code' => 'biblioserver' => { '1' => 'Illustration-code' } );
739 $self->add_bib1_field_map('title' => 'series' => 'biblioserver' => { '1' => '5' } );
740 $self->add_search_field_alias( 'title' => 'series' => 'title-series' );
741 $self->add_search_field_alias( 'title' => 'series' => 'se' );
742 $self->add_bib1_field_map('title' => 'uniform' => 'biblioserver' => { '1' => 'Title-uniform' } );
743 $self->add_search_field_alias( 'title' => 'uniform' => 'title-uniform' );
744 $self->add_bib1_field_map('subject' => 'authority-number' => 'biblioserver' => { '1' => 'Koha-Auth-Number' } );
745 $self->add_search_field_alias( 'subject' => 'authority-number' => 'an' );
746 $self->add_bib1_field_map('keyword' => 'control-number' => 'biblioserver' => { '1' => '9001' } );
747 $self->add_bib1_field_map('keyword' => 'biblionumber' => 'biblioserver' => { '1' => '9002', '5' => '100' } );
748 $self->add_bib1_field_map('keyword' => 'totalissues' => 'biblioserver' => { '1' => '9003' } );
749 $self->add_bib1_field_map('keyword' => 'cn-bib-source' => 'biblioserver' => { '1' => '9004' } );
750 $self->add_bib1_field_map('keyword' => 'cn-bib-sort' => 'biblioserver' => { '1' => '9005' } );
751 $self->add_bib1_field_map('keyword' => 'itemtype' => 'biblioserver' => { '1' => '9006' } );
752 $self->add_search_field_alias( 'keyword' => 'itemtype' => 'mc-itemtype' );
753 $self->add_bib1_field_map('keyword' => 'cn-class' => 'biblioserver' => { '1' => '9007' } );
754 $self->add_bib1_field_map('keyword' => 'cn-item' => 'biblioserver' => { '1' => '9008' } );
755 $self->add_bib1_field_map('keyword' => 'cn-prefix' => 'biblioserver' => { '1' => '9009' } );
756 $self->add_bib1_field_map('keyword' => 'cn-suffix' => 'biblioserver' => { '1' => '9010' } );
757 $self->add_bib1_field_map('keyword' => 'suppress' => 'biblioserver' => { '1' => '9011' } );
758 $self->add_bib1_field_map('keyword' => 'id-other' => 'biblioserver' => { '1' => '9012' } );
759 $self->add_bib1_field_map('keyword' => 'date-entered-on-file' => 'biblioserver' => { '1' => 'date-entered-on-file' } );
760 $self->add_bib1_field_map('keyword' => 'extent' => 'biblioserver' => { '1' => 'Extent' } );
761 $self->add_bib1_field_map('keyword' => 'llength' => 'biblioserver' => { '1' => 'llength' } );
762 $self->add_bib1_field_map('keyword' => 'summary' => 'biblioserver' => { '1' => 'Summary' } );
763 $self->add_bib1_field_map('keyword' => 'withdrawn' => 'biblioserver' => { '1' => '8001' } );
764 $self->add_bib1_field_map('keyword' => 'lost' => 'biblioserver' => { '1' => '8002' } );
765 $self->add_bib1_field_map('keyword' => 'classification-source' => 'biblioserver' => { '1' => '8003' } );
766 $self->add_bib1_field_map('keyword' => 'materials-specified' => 'biblioserver' => { '1' => '8004' } );
767 $self->add_bib1_field_map('keyword' => 'damaged' => 'biblioserver' => { '1' => '8005' } );
768 $self->add_bib1_field_map('keyword' => 'restricted' => 'biblioserver' => { '1' => '8006' } );
769 $self->add_bib1_field_map('keyword' => 'cn-sort' => 'biblioserver' => { '1' => '8007' } );
770 $self->add_bib1_field_map('keyword' => 'notforloan' => 'biblioserver' => { '1' => '8008', '4' => '109' } );
771 $self->add_bib1_field_map('keyword' => 'ccode' => 'biblioserver' => { '1' => '8009' } );
772 $self->add_search_field_alias( 'keyword' => 'ccode' => 'mc-ccode' );
773 $self->add_bib1_field_map('keyword' => 'itemnumber' => 'biblioserver' => { '1' => '8010' } );
774 $self->add_bib1_field_map('keyword' => 'homebranch' => 'biblioserver' => { '1' => 'homebranch' } );
775 $self->add_search_field_alias( 'keyword' => 'homebranch' => 'branch' );
776 $self->add_bib1_field_map('keyword' => 'holdingbranch' => 'biblioserver' => { '1' => '8012' } );
777 $self->add_bib1_field_map('keyword' => 'location' => 'biblioserver' => { '1' => '8013' } );
778 $self->add_search_field_alias( 'keyword' => 'location' => 'mc-loc' );
779 $self->add_bib1_field_map('keyword' => 'acqsource' => 'biblioserver' => { '1' => '8015' } );
780 $self->add_bib1_field_map('keyword' => 'coded-location-qualifier' => 'biblioserver' => { '1' => '8016' } );
781 $self->add_bib1_field_map('keyword' => 'price' => 'biblioserver' => { '1' => '8017' } );
782 $self->add_bib1_field_map('keyword' => 'stocknumber' => 'biblioserver' => { '1' => '1062' } );
783 $self->add_search_field_alias( 'keyword' => 'stocknumber' => 'inv' );
784 $self->add_bib1_field_map('keyword' => 'stack' => 'biblioserver' => { '1' => '8018' } );
785 $self->add_bib1_field_map('keyword' => 'issues' => 'biblioserver' => { '1' => '8019' } );
786 $self->add_bib1_field_map('keyword' => 'renewals' => 'biblioserver' => { '1' => '8020' } );
787 $self->add_bib1_field_map('keyword' => 'reserves' => 'biblioserver' => { '1' => '8021' } );
788 $self->add_bib1_field_map('keyword' => 'local-classification' => 'biblioserver' => { '1' => '8022' } );
789 $self->add_bib1_field_map('keyword' => 'barcode' => 'biblioserver' => { '1' => '8023' } );
790 $self->add_search_field_alias( 'keyword' => 'barcode' => 'bc' );
791 $self->add_bib1_field_map('keyword' => 'onloan' => 'biblioserver' => { '1' => '8024' } );
792 $self->add_bib1_field_map('keyword' => 'datelastseen' => 'biblioserver' => { '1' => '8025' } );
793 $self->add_bib1_field_map('keyword' => 'datelastborrowed' => 'biblioserver' => { '1' => '8026' } );
794 $self->add_bib1_field_map('keyword' => 'copynumber' => 'biblioserver' => { '1' => '8027' } );
795 $self->add_bib1_field_map('keyword' => 'uri' => 'biblioserver' => { '1' => '8028' } );
796 $self->add_bib1_field_map('keyword' => 'replacementprice' => 'biblioserver' => { '1' => '8029' } );
797 $self->add_bib1_field_map('keyword' => 'replacementpricedate' => 'biblioserver' => { '1' => '8030' } );
798 $self->add_bib1_field_map('keyword' => 'itype' => 'biblioserver' => { '1' => '8031' } );
799 $self->add_search_field_alias( 'keyword' => 'itype' => 'mc-itype' );
800 $self->add_bib1_field_map('keyword' => 'ff8-22' => 'biblioserver' => { '1' => '8822' } );
801 $self->add_bib1_field_map('keyword' => 'ff8-23' => 'biblioserver' => { '1' => '8823' } );
802 $self->add_bib1_field_map('keyword' => 'ff8-34' => 'biblioserver' => { '1' => '8834' } );
804 $self->add_bib1_field_map('keyword' => 'audience' => 'biblioserver' => { '1' => '8822' } );
805 $self->add_search_field_alias( 'keyword' => 'audience' => 'aud' );
807 # Content and Literary form
808 $self->add_bib1_field_map('keyword' => 'fiction' => 'biblioserver' => { '1' => '8833' } );
809 $self->add_search_field_alias( 'keyword' => 'fiction' => 'fic' );
810 $self->add_bib1_field_map('keyword' => 'biography' => 'biblioserver' => { '1' => '8834' } );
811 $self->add_search_field_alias( 'keyword' => 'biography' => 'bio' );
814 $self->add_bib1_field_map('keyword' => 'format' => 'biblioserver' => { '1' => '8823' } );
815 # format used as a limit FIXME: needed?
816 $self->add_bib1_field_map('keyword' => 'l-format' => 'biblioserver' => { '1' => '8703' } );
818 $self->add_bib1_field_map('keyword' => 'illustration-code' => 'biblioserver' => { '1' => 'Illustration-code ' } );
821 $self->add_bib1_field_map('keyword' => 'lex' => 'biblioserver' => { '1' => '9903 r=r' } );
823 #Accelerated Reader Level
824 $self->add_bib1_field_map('keyword' => 'arl' => 'biblioserver' => { '1' => '9904 r=r' } );
826 #Accelerated Reader Point
827 $self->add_bib1_field_map('keyword' => 'arp' => 'biblioserver' => { '1' => '9013 r=r' } );
830 $self->add_bib1_field_map('keyword' => 'curriculum' => 'biblioserver' => { '1' => '9658' } );
833 $self->add_bib1_field_map('keyword' => 'popularity' => 'biblioserver' => { '1' => 'issues' } );
836 $self->add_bib1_field_map('keyword' => 'dt-bks' => 'biblioserver' => { '1' => '8700' } );
837 $self->add_bib1_field_map('keyword' => 'dt-vis' => 'biblioserver' => { '1' => '8700' } );
838 $self->add_bib1_field_map('keyword' => 'dt-sr' => 'biblioserver' => { '1' => '8700' } );
839 $self->add_bib1_field_map('keyword' => 'dt-cf' => 'biblioserver' => { '1' => '8700' } );
840 $self->add_bib1_field_map('keyword' => 'dt-map' => 'biblioserver' => { '1' => '8700' } );
842 $self->add_bib1_field_map('keyword' => 'name' => 'biblioserver' => { '1' => '1002' } );
843 $self->add_bib1_field_map('keyword' => 'item' => 'biblioserver' => { '1' => '9520' } );
844 $self->add_bib1_field_map('keyword' => 'host-item-number' => 'biblioserver' => { '1' => '8911' } );
845 $self->add_search_field_alias( 'keyword' => 'host-item-number' => 'hi' );
847 $self->add_bib1_field_map('keyword' => 'alwaysmatch' => 'biblioserver' => { '1' => '_ALLRECORDS', '2' => '103' } );
848 $self->add_bib1_field_map('subject' => 'complete' => 'biblioserver' => { '1' => '21', '3' => '1', '4' => '1', '5' => '100', '6' => '3' } );
850 $self->add_bib1_modifier_map('relevance' => 'biblioserver' => { '2' => '102' } );
851 $self->add_bib1_modifier_map('title-sort-za' => 'biblioserver' => { '7' => '2', '1' => '36', '' => '0', 'op' => '@or' } );
852 $self->add_bib1_modifier_map('title-sort-az' => 'biblioserver' => { '7' => '1', '1' => '36', '' => '0', 'op' => '@or' } );
853 $self->add_bib1_modifier_map('relevance_dsc' => 'biblioserver' => { '2' => '102' } );
854 $self->add_bib1_modifier_map('title_dsc' => 'biblioserver' => { '7' => '2', '1' => '4', '' => '0', 'op' => '@or' } );
855 $self->add_bib1_modifier_map('title_asc' => 'biblioserver' => { '7' => '1', '1' => '4', '' => '0', 'op' => '@or' } );
856 $self->add_bib1_modifier_map('author_asc' => 'biblioserver' => { '7' => '2', '1' => '1003', '' => '0', 'op' => '@or' } );
857 $self->add_bib1_modifier_map('author_dsc' => 'biblioserver' => { '7' => '1', '1' => '1003', '' => '0', 'op' => '@or' } );
858 $self->add_bib1_modifier_map('popularity_asc' => 'biblioserver' => { '7' => '2', '1' => '9003', '' => '0', 'op' => '@or' } );
859 $self->add_bib1_modifier_map('popularity_dsc' => 'biblioserver' => { '7' => '1', '1' => '9003', '' => '0', 'op' => '@or' } );
860 $self->add_bib1_modifier_map('call_number_asc' => 'biblioserver' => { '7' => '2', '1' => '8007', '' => '0', 'op' => '@or' } );
861 $self->add_bib1_modifier_map('call_number_dsc' => 'biblioserver' => { '7' => '1', '1' => '8007', '' => '0', 'op' => '@or' } );
862 $self->add_bib1_modifier_map('pubdate_asc' => 'biblioserver' => { '7' => '2', '1' => '31', '' => '0', 'op' => '@or' } );
863 $self->add_bib1_modifier_map('pubdate_dsc' => 'biblioserver' => { '7' => '1', '1' => '31', '' => '0', 'op' => '@or' } );
864 $self->add_bib1_modifier_map('acqdate_asc' => 'biblioserver' => { '7' => '2', '1' => '32', '' => '0', 'op' => '@or' } );
865 $self->add_bib1_modifier_map('acqdate_dsc' => 'biblioserver' => { '7' => '1', '1' => '32', '' => '0', 'op' => '@or' } );
867 $self->add_bib1_modifier_map('title_za' => 'biblioserver' => { '7' => '2', '1' => '4', '' => '0', 'op' => '@or' } );
868 $self->add_bib1_modifier_map('title_az' => 'biblioserver' => { '7' => '1', '1' => '4', '' => '0', 'op' => '@or' } );
869 $self->add_bib1_modifier_map('author_za' => 'biblioserver' => { '7' => '2', '1' => '1003', '' => '0', 'op' => '@or' } );
870 $self->add_bib1_modifier_map('author_az' => 'biblioserver' => { '7' => '1', '1' => '1003', '' => '0', 'op' => '@or' } );
871 $self->add_bib1_modifier_map('ascending' => 'biblioserver' => { '7' => '1' } );
872 $self->add_bib1_modifier_map('descending' => 'biblioserver' => { '7' => '2' } );
874 $self->add_bib1_field_map('title' => 'exacttitle' => 'biblioserver' => { '1' => '4', '4' => '1', '6' => '3' } );
875 $self->add_search_field_alias( 'title' => 'exacttitle' => 'ti,ext' );
876 $self->add_bib1_field_map('author' => 'exactauthor' => 'biblioserver' => { '1' => '1003', '4' => '1', '6' => '3' } );
877 $self->add_search_field_alias( 'author' => 'exactauthor' => 'au,ext' );
879 $self->add_bib1_field_map('subject' => 'headingmain' => 'authorityserver' => { '1' => 'Heading-Main' } );
880 $self->add_bib1_field_map('subject' => 'heading' => 'authorityserver' => { '1' => 'Heading' } );
881 $self->add_bib1_field_map('subject' => 'matchheading' => 'authorityserver' => { '1' => 'Match-heading' } );
882 $self->add_bib1_field_map('subject' => 'seefrom' => 'authorityserver' => { '1' => 'Match-heading-see-from' } );
883 $self->add_bib1_field_map('subject' => '' => 'authorityserver' => { '1' => 'Match-heading' } );
884 $self->add_bib1_field_map('keyword' => 'alwaysmatch' => 'authorityserver' => { '1' => '_ALLRECORDS', '2' => '103' } );
885 $self->add_bib1_field_map('keyword' => 'match' => 'authorityserver' => { '1' => 'Match' } );
886 $self->add_bib1_field_map('keyword' => 'thesaurus' => 'authorityserver' => { '1' => 'Subject-heading-thesaurus' } );
887 $self->add_bib1_field_map('keyword' => 'authtype' => 'authorityserver' => { '1' => 'authtype', '5' => '100' } );
888 $self->add_bib1_field_map('keyword' => '' => 'authorityserver' => { '1' => 'Any' } );
889 $self->add_search_field_alias( 'subject' => 'headingmain' => 'mainmainentry' );
890 $self->add_search_field_alias( 'subject' => 'heading' => 'mainentry' );
891 $self->add_search_field_alias( 'subject' => 'heading' => 'he' );
892 $self->add_search_field_alias( 'subject' => 'matchheading' => 'match-heading' );
893 $self->add_search_field_alias( 'keyword' => '' => 'any' );
894 $self->add_search_field_alias( 'keyword' => 'match' => 'match' );
895 $self->add_search_field_alias( 'subject' => 'seefrom' => 'see-from' );
896 $self->add_search_field_alias( 'keyword' => 'thesaurus' => 'thesaurus' );
897 $self->add_search_field_alias( 'keyword' => 'alwaysmatch' => 'all' );
898 $self->add_search_field_alias( 'keyword' => 'authtype' => 'authtype' );
899 $self->add_search_field_alias( 'keyword' => 'authtype' => 'at' );
901 $self->add_bib1_field_map('subject' => 'start' => 'authorityserver' => { '3' => '2', '4' => '1', '5' => '1' } );
902 $self->add_bib1_field_map('subject' => 'exact' => 'authorityserver' => { '4' => '1', '5' => '100', '6' => '3' } );
904 $self->add_bib1_modifier_map('HeadingAsc' => 'authorityserver' => { '7' => '1', '1' => 'Heading', '' => '0', 'op' => '@or' } );
905 $self->add_bib1_modifier_map('HeadingDsc' => 'authorityserver' => { '7' => '2', '1' => 'Heading', '' => '0', 'op' => '@or' } );
906 $self->add_bib1_modifier_map('AuthidAsc' => 'authorityserver' => { '7' => '1', '1' => 'Local-Number', '' => '0', 'op' => '@or' } );
907 $self->add_bib1_modifier_map('AuthidDsc' => 'authorityserver' => { '7' => '2', '1' => 'Local-Number', '' => '0', 'op' => '@or' } );
908 $self->add_bib1_modifier_map('Relevance' => 'authorityserver' => { '2' => '102' } );