From 144c7f4e4e023f7a701a1e58524409628295343b 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 +- .../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 b6e3690bbf..e30c571b03 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 c0634ec3a3..6a7c4f2226 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 bde9cc8ade..72ca5be060 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 fdc41c5a41..7df5fa2e03 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 c8a8071025..f643599635 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 f317f8b2fb..f30086e62f 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 acc085474b..020243859d 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 ef7d9bf24a..eeb46f8f9c 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 e0f905c91f..682af89508 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 623efe28f9..95e4aa770e 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 6d3d7a34ec..28bee106be 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); } -- 2.20.1