From 084e1003fe16a0aea69d99e157bbb0cbca06e5a8 Mon Sep 17 00:00:00 2001 From: Jared Camins-Esakov Date: Tue, 11 Dec 2012 12:52:40 -0500 Subject: [PATCH] Bug 9239: Allow the use of QueryParser for all queries With the inclusion of this patch, all searches will (try) to use QueryParser for handling queries for both the bibliographic and authority databases if UseQueryParser is enabled. If QueryParser is unavailable, UseQueryParser is disabled, or the search uses CCL indexes, the old search code will be used. To test: 1) Apply patch. 2) Run the unit test with `prove t/QueryParser.t` 3) Enable the UseQueryParser syspref. 4) Try searches that should return results in the following places: * OPAC (simple search) * OPAC (advanced search) * OPAC (authorities) * Staff client (header search) * Staff client (advanced search) * Staff client (cataloging search) * Staff client (authorities) * Staff client (importing a batch using a match point) * Staff client (searching for an item for adding to a label) * Staff client (acquisitions) * Staff client (searching for a record to create a serial) * ANYWHERE ELSE I HAVE FORGOTTEN 5) Disable the UseQueryParser syspref. Repeat at least some of the searches you did above. 6) If all searches worked, sign off. Signed-off-by: Chris Cormack Signed-off-by: Elliott Davis Searching still works as expected for variuos places. QueryParser syspref seemed to be enabled by default Signed-off-by: Katrin Fischer Signed-off-by: Jared Camins-Esakov --- C4/AuthoritiesMarc.pm | 40 ++++++- C4/Matcher.pm | 55 +++++----- C4/Search.pm | 113 +++++++++++++------- Koha/SuggestionEngine/Plugin/AuthorityFile.pm | 2 +- cataloguing/addbooks.pl | 10 +- .../value_builder/marc21_linking_section.pl | 10 +- cataloguing/value_builder/unimarc_field_4XX.pl | 10 +- labels/label-item-search.pl | 25 +++-- misc/migration_tools/bulkmarcimport.pl | 22 +++- serials/subscription-bib-search.pl | 18 +++- t/db_dependent/Search.t | 21 ++-- 11 files changed, 236 insertions(+), 90 deletions(-) diff --git a/C4/AuthoritiesMarc.pm b/C4/AuthoritiesMarc.pm index b6e3690..e30c571 100644 --- a/C4/AuthoritiesMarc.pm +++ b/C4/AuthoritiesMarc.pm @@ -201,6 +201,9 @@ sub SearchAuthorities { } } else { my $query; + my $qpquery = ''; + my $QParser; + $QParser = C4::Context->queryparser if (C4::Context->preference('UseQueryParser')); my $attr = ''; # the marclist may contain "mainentry". In this case, search the tag_to_report, that depends on # the authtypecode. Then, search on $a of this tag_to_report @@ -219,6 +222,9 @@ sub SearchAuthorities { if ($n>1){ while ($n>1){$query= "\@or ".$query;$n--;} } + if ($QParser) { + $qpquery .= '(authtype:' . join('|| authtype:', @auths) . ')'; + } } my $dosearch; @@ -276,6 +282,9 @@ sub SearchAuthorities { $q2 .=$attr; $dosearch=1; ++$attr_cnt; + if ($QParser) { + $qpquery .= " $tags->[$i]:$value->[$i]"; + } }#if value } ##Add how many queries generated @@ -296,8 +305,21 @@ sub SearchAuthorities { } elsif ($sortby eq 'AuthidDsc') { $orderstring = '@attr 7=2 @attr 4=109 @attr 1=Local-Number 0'; } - $query=($query?$query:"\@attr 1=_ALLRECORDS \@attr 2=103 ''"); - $query="\@or $orderstring $query" if $orderstring; + if ($QParser) { + $qpquery .= ' all:all' unless $value->[0]; + + if ( $value->[0] =~ m/^qp=(.*)$/ ) { + $qpquery = $1; + } + + $qpquery .= " #$sortby"; + + $QParser->parse( $qpquery ); + $query = $QParser->target_syntax('authorityserver'); + } else { + $query=($query?$query:"\@attr 1=_ALLRECORDS \@attr 2=103 ''"); + $query="\@or $orderstring $query" if $orderstring; + } $offset=0 unless $offset; my $counter = $offset; @@ -406,7 +428,7 @@ sub CountUsage { } else { ### ZOOM search here my $query; - $query= "an=".$authid; + $query= "an:".$authid; my ($err,$res,$result) = C4::Search::SimpleSearch($query,0,10); if ($err) { warn "Error: $err from search $query"; @@ -911,11 +933,19 @@ sub FindDuplicateAuthority { $sth->finish; # warn "record :".$record->as_formatted." auth_tag_to_report :$auth_tag_to_report"; # build a request for SearchAuthorities - my $query='at='.$authtypecode.' '; + my $QParser; + $QParser = C4::Context->queryparser if (C4::Context->preference('UseQueryParser')); + my $op; + if ($QParser) { + $op = '&&'; + } else { + $op = 'and'; + } + my $query='at:'.$authtypecode.' '; my $filtervalues=qr([\001-\040\!\'\"\`\#\$\%\&\*\+,\-\./:;<=>\?\@\(\)\{\[\]\}_\|\~]); if ($record->field($auth_tag_to_report)) { foreach ($record->field($auth_tag_to_report)->subfields()) { - $_->[1]=~s/$filtervalues/ /g; $query.= " and he,wrdl=\"".$_->[1]."\"" if ($_->[0]=~/[A-z]/); + $_->[1]=~s/$filtervalues/ /g; $query.= " $op he:\"".$_->[1]."\"" if ($_->[0]=~/[A-z]/); } } my ($error, $results, $total_hits) = C4::Search::SimpleSearch( $query, 0, 1, [ "authorityserver" ] ); diff --git a/C4/Matcher.pm b/C4/Matcher.pm index c0634ec..6a7c4f2 100644 --- a/C4/Matcher.pm +++ b/C4/Matcher.pm @@ -626,6 +626,8 @@ sub get_matches { my %matches = (); + my $QParser; + $QParser = C4::Context->queryparser if (C4::Context->preference('UseQueryParser')); foreach my $matchpoint (@{ $self->{'matchpoints'} }) { my @source_keys = _get_match_keys($source_record, $matchpoint); next if scalar(@source_keys) == 0; @@ -634,31 +636,36 @@ sub get_matches { my $error; my $searchresults; my $total_hits; - if ($self->{'record_type'} eq 'biblio') { - $query = join(" or ", map { "$matchpoint->{'index'}=$_" } @source_keys); -# FIXME only searching biblio index at the moment + if ($QParser) { + $query = join(" || ", map { "$matchpoint->{'index'}:$_" } @source_keys); require C4::Search; - ($error, $searchresults, $total_hits) = C4::Search::SimpleSearch($query, 0, $max_matches); - } elsif ($self->{'record_type'} eq 'authority') { - my $authresults; - my @marclist; - my @and_or; - my @excluding = []; - my @operator; - my @value; - foreach my $key (@source_keys) { - push @marclist, $matchpoint->{'index'}; - push @and_or, 'or'; - push @operator, 'exact'; - push @value, $key; - } - require C4::AuthoritiesMarc; - ($authresults, $total_hits) = C4::AuthoritiesMarc::SearchAuthorities( - \@marclist, \@and_or, \@excluding, \@operator, - \@value, 0, 20, undef, 'AuthidAsc', 1 - ); - foreach my $result (@$authresults) { - push @$searchresults, $result->{'authid'}; + ($error, $searchresults, $total_hits) = C4::Search::SimpleSearch($query, 0, $max_matches, [ $self->{'record_type'} . 'server' ] ); + } else { + if ($self->{'record_type'} eq 'biblio') { + $query = join(" or ", map { "$matchpoint->{'index'}=$_" } @source_keys); + require C4::Search; + ($error, $searchresults, $total_hits) = C4::Search::SimpleSearch($query, 0, $max_matches); + } elsif ($self->{'record_type'} eq 'authority') { + my $authresults; + my @marclist; + my @and_or; + my @excluding = []; + my @operator; + my @value; + foreach my $key (@source_keys) { + push @marclist, $matchpoint->{'index'}; + push @and_or, 'or'; + push @operator, 'exact'; + push @value, $key; + } + require C4::AuthoritiesMarc; + ($authresults, $total_hits) = C4::AuthoritiesMarc::SearchAuthorities( + \@marclist, \@and_or, \@excluding, \@operator, + \@value, 0, 20, undef, 'AuthidAsc', 1 + ); + foreach my $result (@$authresults) { + push @$searchresults, $result->{'authid'}; + } } } diff --git a/C4/Search.pm b/C4/Search.pm index ce6129d..4039a68 100644 --- a/C4/Search.pm +++ b/C4/Search.pm @@ -100,9 +100,25 @@ sub FindDuplicate { if ( $result->{isbn} ) { $result->{isbn} =~ s/\(.*$//; $result->{isbn} =~ s/\s+$//; - $query = "isbn=$result->{isbn}"; + $query = "isbn:$result->{isbn}"; } else { + my $QParser; + $QParser = C4::Context->queryparser if (C4::Context->preference('UseQueryParser')); + my $titleindex; + my $authorindex; + my $op; + + if ($QParser) { + $titleindex = 'title|exact'; + $authorindex = 'author|exact'; + $op = '&&'; + } else { + $titleindex = 'ti,ext'; + $authorindex = 'au,ext'; + $op = 'and'; + } + $result->{title} =~ s /\\//g; $result->{title} =~ s /\"//g; $result->{title} =~ s /\(//g; @@ -111,7 +127,7 @@ sub FindDuplicate { # FIXME: instead of removing operators, could just do # quotes around the value $result->{title} =~ s/(and|or|not)//g; - $query = "ti,ext=$result->{title}"; + $query = "$titleindex:\"$result->{title}\""; if ( $result->{author} ) { $result->{author} =~ s /\\//g; $result->{author} =~ s /\"//g; @@ -120,7 +136,7 @@ sub FindDuplicate { # remove valid operators $result->{author} =~ s/(and|or|not)//g; - $query .= " and au,ext=$result->{author}"; + $query .= " $op $authorindex:\"$result->{author}\""; } } @@ -224,11 +240,21 @@ sub SimpleSearch { my $results = []; my $total_hits = 0; + my $QParser; + $QParser = C4::Context->queryparser if (C4::Context->preference('UseQueryParser') && ! ($query =~ m/\w,\w|\w=\w/)); + # Initialize & Search Zebra for ( my $i = 0 ; $i < @servers ; $i++ ) { eval { $zconns[$i] = C4::Context->Zconn( $servers[$i], 1 ); - $zoom_queries[$i] = new ZOOM::Query::CCL2RPN( $query, $zconns[$i]); + if ($QParser) { + $query =~ s/=/:/g; + $QParser->parse( $query ); + $query = $QParser->target_syntax($servers[$i]); + $zoom_queries[$i] = new ZOOM::Query::PQF( $query, $zconns[$i]); + } else { + $zoom_queries[$i] = new ZOOM::Query::CCL2RPN( $query, $zconns[$i]); + } $tmpresults[$i] = $zconns[$i]->search( $zoom_queries[$i] ); # error handling @@ -1091,7 +1117,9 @@ on authority data). =cut sub _handle_exploding_index { - my ( $index, $term ) = @_; + my ($QParser, $struct, $filter, $params, $negate, $server) = @_; + my $index = $filter; + my $term = join(' ', @$params); return unless ($index =~ m/(su-br|su-na|su-rl)/ && $term); @@ -1099,8 +1127,8 @@ sub _handle_exploding_index { my $codesubfield = $marcflavour eq 'UNIMARC' ? '5' : 'w'; my $wantedcodes = ''; - my @subqueries = ( "(su=\"$term\")"); - my ($error, $results, $total_hits) = SimpleSearch( "Heading,wrdl=$term", undef, undef, [ "authorityserver" ] ); + my @subqueries = ( "su:\"$term\""); + my ($error, $results, $total_hits) = SimpleSearch( "he:$term", undef, undef, [ "authorityserver" ] ); foreach my $auth (@$results) { my $record = MARC::Record->new_from_usmarc($auth); my @references = $record->field('5..'); @@ -1114,11 +1142,13 @@ sub _handle_exploding_index { } foreach my $reference (@references) { my $codes = $reference->subfield($codesubfield); - push @subqueries, '(su="' . $reference->as_string('abcdefghijlmnopqrstuvxyz') . '")' if (($codes && $codes eq $wantedcodes) || !$wantedcodes); + push @subqueries, 'su:"' . $reference->as_string('abcdefghijlmnopqrstuvxyz') . '"' if (($codes && $codes eq $wantedcodes) || !$wantedcodes); } } } - return join(' or ', @subqueries); + my $query = '(' x scalar(@subqueries) . join(') || ', @subqueries) . ')'; + warn $query; + return $query; } =head2 parseQuery @@ -1145,37 +1175,42 @@ sub parseQuery { my $query = $operands[0]; my $index; my $term; + my $query_desc; -# TODO: once we are using QueryParser, all this special case code for -# exploded search indexes will be replaced by a callback to -# _handle_exploding_index - if ( $query =~ m/^(.*)\b(su-br|su-na|su-rl)[:=](\w.*)$/ ) { - $query = $1; - $index = $2; - $term = $3; - } else { + my $QParser; + $QParser = C4::Context->queryparser if (C4::Context->preference('UseQueryParser') || $query =~ s/^qp=//); + undef $QParser if ($query =~ m/^(ccl=|pqf=|cql=)/ || grep (/\w,\w|\w=\w/, @operands) ); + + if ($QParser) + { $query = ''; - for ( my $i = 0 ; $i <= @operands ; $i++ ) { - if ($operands[$i] && $indexes[$i] =~ m/(su-br|su-na|su-rl)/) { - $index = $indexes[$i]; - $term = $operands[$i]; - } elsif ($operands[$i]) { - $query .= $operators[$i] eq 'or' ? ' or ' : ' and ' if ($query); - $query .= "($indexes[$i]:$operands[$i])"; - } + for ( my $ii = 0 ; $ii <= @operands ; $ii++ ) { + next unless $operands[$ii]; + $query .= $operators[ $ii - 1 ] eq 'or' ? ' || ' : ' && ' + if ($query); + $query .= + ( $operators[$ii] ? "$operators[$ii]:" : '' ) . $operands[$ii]; + } + foreach my $limit (@limits) { + } + foreach my $modifier (@sort_by) { + $query .= " #$modifier"; } - } - if ($index) { - my $queryPart = _handle_exploding_index($index, $term); - if ($queryPart) { - $query .= "($queryPart)"; + $query_desc = $query; + if ( C4::Context->preference("QueryWeightFields") ) { } - $operators = (); - $operands[0] = "ccl=$query"; + $QParser->add_bib1_filter_map( 'biblioserver', 'su-br', { 'callback' => \&_handle_exploding_index }); + $QParser->add_bib1_filter_map( 'biblioserver', 'su-na', { 'callback' => \&_handle_exploding_index }); + $QParser->add_bib1_filter_map( 'biblioserver', 'su-rl', { 'callback' => \&_handle_exploding_index }); + $QParser->parse( $query ); + $operands[0] = "pqf=" . $QParser->target_syntax('biblioserver'); +# TODO: once we are using QueryParser, all this special case code for +# exploded search indexes will be replaced by a callback to +# _handle_exploding_index } - return ( $operators, \@operands, $indexes, $limits, $sort_by, $scan, $lang); + return ( $operators, \@operands, $indexes, $limits, $sort_by, $scan, $lang, $query_desc); } =head2 buildQuery @@ -1199,7 +1234,8 @@ sub buildQuery { warn "---------\nEnter buildQuery\n---------" if $DEBUG; - ( $operators, $operands, $indexes, $limits, $sort_by, $scan, $lang) = parseQuery($operators, $operands, $indexes, $limits, $sort_by, $scan, $lang); + my $query_desc; + ( $operators, $operands, $indexes, $limits, $sort_by, $scan, $lang, $query_desc) = parseQuery($operators, $operands, $indexes, $limits, $sort_by, $scan, $lang); # dereference my @operators = $operators ? @$operators : (); @@ -1227,7 +1263,6 @@ sub buildQuery { # initialize the variables we're passing back my $query_cgi; - my $query_desc; my $query_type; my $limit; @@ -1262,7 +1297,13 @@ sub buildQuery { return ( undef, $', $', "q=cql=$'", $', '', '', '', '', 'cql' ); } if ( $query =~ /^pqf=/ ) { - return ( undef, $', $', "q=pqf=$'", $', '', '', '', '', 'pqf' ); + if ($query_desc) { + $query_cgi = "q=$query_desc"; + } else { + $query_desc = $'; + $query_cgi = "q=pqf=$'"; + } + return ( undef, $', $', $query_cgi, $query_desc, '', '', '', '', 'pqf' ); } # pass nested queries directly diff --git a/Koha/SuggestionEngine/Plugin/AuthorityFile.pm b/Koha/SuggestionEngine/Plugin/AuthorityFile.pm index fdc41c5..7df5fa2 100644 --- a/Koha/SuggestionEngine/Plugin/AuthorityFile.pm +++ b/Koha/SuggestionEngine/Plugin/AuthorityFile.pm @@ -85,7 +85,7 @@ sub get_suggestions { # FIXME: calling into C4 require C4::AuthoritiesMarc; my ( $searchresults, $count ) = C4::AuthoritiesMarc::SearchAuthorities( - \@marclist, \@and_or, \@excluding, \@operator, + @marclist, @and_or, @excluding, @operator, @value, 0, $param->{'count'}, '', 'Relevance', 0 ); diff --git a/cataloguing/addbooks.pl b/cataloguing/addbooks.pl index c8a8071..f643599 100755 --- a/cataloguing/addbooks.pl +++ b/cataloguing/addbooks.pl @@ -70,10 +70,16 @@ if ($query) { # build query my @operands = $query; - my ( $builterror,$builtquery,$simple_query,$query_cgi,$query_desc,$limit,$limit_cgi,$limit_desc,$stopwords_removed,$query_type) = buildQuery(undef,\@operands); + + my $QParser; + $QParser = C4::Context->queryparser if (C4::Context->preference('UseQueryParser')); + unless ($QParser) { + my ( $builterror,$builtquery,$simple_query,$query_cgi,$query_desc,$limit,$limit_cgi,$limit_desc,$stopwords_removed,$query_type) = buildQuery(undef,\@operands); + $query = $builtquery; + } # find results - my ( $error, $marcresults, $total_hits ) = SimpleSearch($builtquery, $results_per_page * ($page - 1), $results_per_page); + my ( $error, $marcresults, $total_hits ) = SimpleSearch($query, $results_per_page * ($page - 1), $results_per_page); if ( defined $error ) { $template->param( error => $error ); diff --git a/cataloguing/value_builder/marc21_linking_section.pl b/cataloguing/value_builder/marc21_linking_section.pl index f317f8b..f30086e 100644 --- a/cataloguing/value_builder/marc21_linking_section.pl +++ b/cataloguing/value_builder/marc21_linking_section.pl @@ -190,7 +190,15 @@ sub plugin { my $startfrom = $query->param('startfrom'); my $resultsperpage = $query->param('resultsperpage') || 20; my $orderby; - $search = 'kw,wrdl=' . $search . ' and mc-itemtype=' . $itype if $itype; + my $QParser; + $QParser = C4::Context->queryparser if (C4::Context->preference('UseQueryParser')); + my $op; + if ($QParser) { + $op = '&&'; + } else { + $op = 'and'; + } + $search = 'kw:' . $search . " $op mc-itemtype:" . $itype if $itype; my ( $errors, $results, $total_hits ) = SimpleSearch( $search, $startfrom * $resultsperpage, $resultsperpage ); diff --git a/cataloguing/value_builder/unimarc_field_4XX.pl b/cataloguing/value_builder/unimarc_field_4XX.pl index acc0854..0202438 100755 --- a/cataloguing/value_builder/unimarc_field_4XX.pl +++ b/cataloguing/value_builder/unimarc_field_4XX.pl @@ -341,7 +341,15 @@ sub plugin { my $startfrom = $query->param('startfrom'); my $resultsperpage = $query->param('resultsperpage') || 20; my $orderby; - $search = 'kw,wrdl='.$search.' and mc-itemtype='.$itype if $itype; + my $QParser; + $QParser = C4::Context->queryparser if (C4::Context->preference('UseQueryParser')); + my $op; + if ($QParser) { + $op = '&&'; + } else { + $op = 'and'; + } + $search = 'kw:'.$search." $op mc-itemtype:".$itype if $itype; my ( $errors, $results, $total_hits ) = SimpleSearch($search, $startfrom * $resultsperpage, $resultsperpage ); if (defined $errors ) { $results = []; diff --git a/labels/label-item-search.pl b/labels/label-item-search.pl index ef7d9bf..eeb46f8 100755 --- a/labels/label-item-search.pl +++ b/labels/label-item-search.pl @@ -66,10 +66,12 @@ my $display_columns = [ {_add => {label => "Add Item", link_fi ]; if ( $op eq "do_search" ) { + my $QParser; + $QParser = C4::Context->queryparser if (C4::Context->preference('UseQueryParser')); $idx = $query->param('idx'); $ccl_textbox = $query->param('ccl_textbox'); if ( $ccl_textbox && $idx ) { - $ccl_query = "$idx=$ccl_textbox"; + $ccl_query = "$idx:$ccl_textbox"; } $datefrom = $query->param('datefrom'); @@ -77,15 +79,26 @@ if ( $op eq "do_search" ) { if ($datefrom) { $datefrom = C4::Dates->new($datefrom); - $ccl_query .= ' and ' if $ccl_textbox; - $ccl_query .= - "acqdate,st-date-normalized,ge=" . $datefrom->output("iso"); + if ($QParser) { + $ccl_query .= ' && ' if $ccl_textbox; + $ccl_query .= + "acqdate(" . $datefrom->output("iso") . '-)'; + } else { + $ccl_query .= ' and ' if $ccl_textbox; + $ccl_query .= + "acqdate,st-date-normalized,ge=" . $datefrom->output("iso"); + } } if ($dateto) { $dateto = C4::Dates->new($dateto); - $ccl_query .= ' and ' if ( $ccl_textbox || $datefrom ); - $ccl_query .= "acqdate,st-date-normalized,le=" . $dateto->output("iso"); + if ($QParser) { + $ccl_query .= ' && ' if ( $ccl_textbox || $datefrom ); + $ccl_query .= "acqdate(-" . $dateto->output("iso") . ')'; + } else { + $ccl_query .= ' and ' if ( $ccl_textbox || $datefrom ); + $ccl_query .= "acqdate,st-date-normalized,le=" . $datefrom->output("iso"); + } } my $offset = $startfrom > 1 ? $startfrom - 1 : 0; diff --git a/misc/migration_tools/bulkmarcimport.pl b/misc/migration_tools/bulkmarcimport.pl index e0f905c..682af89 100755 --- a/misc/migration_tools/bulkmarcimport.pl +++ b/misc/migration_tools/bulkmarcimport.pl @@ -432,7 +432,15 @@ sub build_query { my $string = build_simplequery($matchingpoint,$record); push @searchstrings,$string if (length($string)>0); } - return join(" and ",@searchstrings); + my $QParser; + $QParser = C4::Context->queryparser if (C4::Context->preference('UseQueryParser')); + my $op; + if ($QParser) { + $op = '&&'; + } else { + $op = 'and'; + } + return join(" $op ",@searchstrings); } sub build_simplequery { my $element=shift; @@ -442,10 +450,18 @@ sub build_simplequery { my @searchstrings; foreach my $field ($record->field($tag)){ if (length($field->as_string("$subfields"))>0){ - push @searchstrings,"$index,wrdl=\"".$field->as_string("$subfields")."\""; + push @searchstrings,"$index:\"".$field->as_string("$subfields")."\""; } } - return join(" and ",@searchstrings); + my $QParser; + $QParser = C4::Context->queryparser if (C4::Context->preference('UseQueryParser')); + my $op; + if ($QParser) { + $op = '&&'; + } else { + $op = 'and'; + } + return join(" $op ",@searchstrings); } sub report_item_errors { my $biblionumber = shift; diff --git a/serials/subscription-bib-search.pl b/serials/subscription-bib-search.pl index 623efe2..95e4aa7 100755 --- a/serials/subscription-bib-search.pl +++ b/serials/subscription-bib-search.pl @@ -90,11 +90,19 @@ if ($op eq "do_search" && $query) { # add the itemtype limit if applicable my $itemtypelimit = $input->param('itemtypelimit'); if ( $itemtypelimit ) { - if (!$advanced_search_types or $advanced_search_types eq 'itemtypes') { - $query .= " AND $itype_or_itemtype=$itemtypelimit"; - } else { - $query .= " AND $advanced_search_types=$itemtypelimit"; - } + my $QParser; + $QParser = C4::Context->queryparser if (C4::Context->preference('UseQueryParser')); + my $op; + if ($QParser) { + $op = '&&'; + } else { + $op = 'and'; + } + if (!$advanced_search_types or $advanced_search_types eq 'itemtypes') { + $query .= " $op $itype_or_itemtype:$itemtypelimit"; + } else { + $query .= " $op $advanced_search_types:$itemtypelimit"; + } } $debug && warn $query; $resultsperpage= $input->param('resultsperpage'); diff --git a/t/db_dependent/Search.t b/t/db_dependent/Search.t index 6d3d7a3..28bee10 100644 --- a/t/db_dependent/Search.t +++ b/t/db_dependent/Search.t @@ -32,6 +32,7 @@ my $QueryAutoTruncate = 0; my $QueryWeightFields = 0; my $QueryFuzzy = 0; my $QueryRemoveStopwords = 0; +my $UseQueryParser = 0; my $contextmodule = new Test::MockModule('C4::Context'); $contextmodule->mock('_new_dbh', sub { my $dbh = DBI->connect( 'DBI:Mock:', '', '' ) @@ -53,6 +54,8 @@ $contextmodule->mock('preference', sub { return $QueryFuzzy; } elsif ($pref eq 'QueryRemoveStopwords') { return $QueryRemoveStopwords; + } elsif ($pref eq 'UseQueryParser') { + return $UseQueryParser; } elsif ($pref eq 'maxRecordsForFacets') { return 20; } elsif ($pref eq 'FacetLabelTruncationLength') { @@ -109,6 +112,11 @@ $contextmodule->mock('marcfromkohafield', sub { ); return \%hash; }); +$contextmodule->mock('queryparser', sub { + my $QParser = Koha::QueryParser::Driver::PQF->new(); + $QParser->load_config("$datadir/etc/searchengine/queryparser.yaml"); + return $QParser; +}); my $context = new C4::Context("$datadir/etc/koha-conf.xml"); $context->set_context(); @@ -521,7 +529,7 @@ my $searchmodule = new Test::MockModule('C4::Search'); $searchmodule->mock('SimpleSearch', sub { my $query = shift; - is($query, "Heading,wrdl=$term", "Searching for expected term '$term' for exploding") or return '', [], 0; + is($query, "he:$term", "Searching for expected term '$term' for exploding") or return '', [], 0; my $record = MARC::Record->new; if ($query =~ m/Arizona/) { @@ -538,6 +546,7 @@ $searchmodule->mock('SimpleSearch', sub { return '', [ $record->as_usmarc() ], 1; }); +$UseQueryParser = 1; $term = 'Arizona'; ( $error, $query, $simple_query, $query_cgi, $query_desc, $limit, $limit_cgi, $limit_desc, @@ -568,28 +577,28 @@ like($query, qr/history/, "Order of terms doesn't matter for advanced search"); ( $error, $query, $simple_query, $query_cgi, $query_desc, $limit, $limit_cgi, $limit_desc, -$stopwords_removed, $query_type ) = buildQuery([], [ "su-br:$term" ], [ ], [ ], [], 0, 'en'); +$stopwords_removed, $query_type ) = buildQuery([], [ "su-br($term)" ], [ ], [ ], [], 0, 'en'); matchesExplodedTerms("Simple search for broader subjects", $query, 'Arizona', 'United States'); ( $error, $query, $simple_query, $query_cgi, $query_desc, $limit, $limit_cgi, $limit_desc, -$stopwords_removed, $query_type ) = buildQuery([], [ "su-na:$term" ], [ ], [ ], [], 0, 'en'); +$stopwords_removed, $query_type ) = buildQuery([], [ "su-na($term)" ], [ ], [ ], [], 0, 'en'); matchesExplodedTerms("Simple search for narrower subjects", $query, 'Arizona', 'Maricopa County', 'Navajo County', 'Pima County'); ( $error, $query, $simple_query, $query_cgi, $query_desc, $limit, $limit_cgi, $limit_desc, -$stopwords_removed, $query_type ) = buildQuery([], [ "su-rl:$term" ], [ ], [ ], [], 0, 'en'); +$stopwords_removed, $query_type ) = buildQuery([], [ "su-rl($term)" ], [ ], [ ], [], 0, 'en'); matchesExplodedTerms("Simple search for related subjects", $query, 'Arizona', 'United States', 'Maricopa County', 'Navajo County', 'Pima County'); ( $error, $query, $simple_query, $query_cgi, $query_desc, $limit, $limit_cgi, $limit_desc, -$stopwords_removed, $query_type ) = buildQuery([], [ "history and su-rl:$term" ], [ ], [ ], [], 0, 'en'); +$stopwords_removed, $query_type ) = buildQuery([], [ "history && su-rl($term)" ], [ ], [ ], [], 0, 'en'); matchesExplodedTerms("Simple search for related subjects and keyword 'history' searches related subjects", $query, 'Arizona', 'United States', 'Maricopa County', 'Navajo County', 'Pima County'); like($query, qr/history/, "Simple search for related subjects and keyword 'history' searches for 'history'"); sub matchesExplodedTerms { my ($message, $query, @terms) = @_; - my $match = "(( or )?\\((" . join ('|', map { "su=\"$_\"" } @terms) . ")\\)){" . scalar(@terms) . "}"; + my $match = '(' . join ('|', map { " \@attr 1=Subject \@attr 4=1 \"$_\"" } @terms) . "){" . scalar(@terms) . "}"; like($query, qr/$match/, $message); } -- 1.7.9.5