#!/usr/local/bin/perl -T # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. use strict; use warnings; # (Change configuration variables as needed.) my $path_to_index = '/path/to/index'; use CGI; use List::Util qw( max min ); use POSIX qw( ceil ); use Encode qw( decode ); use Lucy::Search::IndexSearcher; use Lucy::Highlight::Highlighter; use Lucy::Search::QueryParser; use Lucy::Search::TermQuery; use Lucy::Search::ANDQuery; my $cgi = CGI->new; my $q = decode( "UTF-8", $cgi->param('q') || '' ); my $offset = decode( "UTF-8", $cgi->param('offset') || 0 ); my $category = decode( "UTF-8", $cgi->param('category') || '' ); my $page_size = 10; # Create an IndexSearcher and a QueryParser. my $searcher = Lucy::Search::IndexSearcher->new( index => $path_to_index, ); my $qparser = Lucy::Search::QueryParser->new( schema => $searcher->get_schema, ); # Build up a Query. my $query = $qparser->parse($q); if ($category) { my $category_query = Lucy::Search::TermQuery->new( field => 'category', term => $category, ); $query = Lucy::Search::ANDQuery->new( children => [ $query, $category_query ] ); } # Execute the Query and get a Hits object. my $hits = $searcher->hits( query => $query, offset => $offset, num_wanted => $page_size, ); my $hit_count = $hits->total_hits; # Arrange for highlighted excerpts to be created. my $highlighter = Lucy::Highlight::Highlighter->new( searcher => $searcher, query => $q, field => 'content' ); # Create result list. my $report = ''; while ( my $hit = $hits->next ) { my $score = sprintf( "%0.3f", $hit->get_score ); my $excerpt = $highlighter->create_excerpt($hit); $report .= qq|

$hit->{title} $score
$excerpt
$hit->{url}

|; } #--------------------------------------------------------------------# # No Lucy tutorial material below this point - just html generation. # #--------------------------------------------------------------------# # Generate html, print and exit. my $paging_links = generate_paging_info( $q, $hit_count ); my $cat_select = generate_category_select($category); blast_out_content( $q, $report, $paging_links, $cat_select ); # Create html fragment with links for paging through results n-at-a-time. sub generate_paging_info { my ( $query_string, $total_hits ) = @_; my $escaped_q = CGI::escapeHTML($query_string); my $paging_info; if ( !length $query_string ) { # No query? No display. $paging_info = ''; } elsif ( $total_hits == 0 ) { # Alert the user that their search failed. $paging_info = qq|

No matches for $escaped_q

|; } else { # Calculate the nums for the first and last hit to display. my $last_result = min( ( $offset + $page_size ), $total_hits ); my $first_result = min( ( $offset + 1 ), $last_result ); # Display the result nums, start paging info. $paging_info = qq|

Results $first_result-$last_result of $total_hits for $escaped_q.

Results Page: |; # Calculate first and last hits pages to display / link to. my $current_page = int( $first_result / $page_size ) + 1; my $last_page = ceil( $total_hits / $page_size ); my $first_page = max( 1, ( $current_page - 9 ) ); $last_page = min( $last_page, ( $current_page + 10 ) ); # Create a url for use in paging links. my $href = $cgi->url( -relative => 1 ); $href .= "?q=" . CGI::escape($query_string); $href .= ";category=" . CGI::escape($category); $href .= ";offset=" . CGI::escape($offset); # Generate the "Prev" link. if ( $current_page > 1 ) { my $new_offset = ( $current_page - 2 ) * $page_size; $href =~ s/(?<=offset=)\d+/$new_offset/; $paging_info .= qq|<= Prev\n|; } # Generate paging links. for my $page_num ( $first_page .. $last_page ) { if ( $page_num == $current_page ) { $paging_info .= qq|$page_num \n|; } else { my $new_offset = ( $page_num - 1 ) * $page_size; $href =~ s/(?<=offset=)\d+/$new_offset/; $paging_info .= qq|$page_num\n|; } } # Generate the "Next" link. if ( $current_page != $last_page ) { my $new_offset = $current_page * $page_size; $href =~ s/(?<=offset=)\d+/$new_offset/; $paging_info .= qq|Next =>\n|; } # Close tag. $paging_info .= "

\n"; } return $paging_info; } # Build up the HTML "select" object for the "category" field. sub generate_category_select { my $cat = shift; my $select = qq| |; if ($cat) { $select =~ s/"$cat"/"$cat" selected/; } return $select; } # Print content to output. sub blast_out_content { my ( $query_string, $hit_list, $paging_info, $category_select ) = @_; my $escaped_q = CGI::escapeHTML($query_string); binmode( STDOUT, ":encoding(UTF-8)" ); print qq|Content-type: text/html; charset=UTF-8\n\n|; print qq| Lucy: $escaped_q
$hit_list $paging_info

Powered by Apache LucyTM

|; }