⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 searcher.pm

📁 外国人写的Perl搜索引擎程序
💻 PM
字号:
package KinoSearch::Searcher;use strict;use warnings;use KinoSearch::Util::ToolSet;use base qw( KinoSearch::Search::Searchable );BEGIN {    __PACKAGE__->init_instance_vars(        # params/members        invindex => undef,        analyzer => undef,        # members        reader       => undef,        close_reader => 0,       # not implemented yet    );    __PACKAGE__->ready_get(qw( reader ));}use KinoSearch::Store::FSInvIndex;use KinoSearch::Index::IndexReader;use KinoSearch::Search::Hits;use KinoSearch::Search::HitCollector;use KinoSearch::Search::Similarity;use KinoSearch::QueryParser::QueryParser;use KinoSearch::Search::BooleanQuery;use KinoSearch::Analysis::Analyzer;sub init_instance {    my $self = shift;    $self->{analyzer} ||= KinoSearch::Analysis::Analyzer->new;    $self->{similarity} = KinoSearch::Search::Similarity->new;    $self->{field_sims} = {};    if ( !defined $self->{reader} ) {        # confirm or create an InvIndex object        my $invindex;        if ( blessed( $self->{invindex} )            and $self->{invindex}->isa('KinoSearch::Store::InvIndex') )        {            $invindex = $self->{invindex};        }        elsif ( defined $self->{invindex} ) {            $invindex = $self->{invindex}                = KinoSearch::Store::FSInvIndex->new(                create => $self->{create},                path   => $self->{invindex},                );        }        else {            croak("valid 'reader' or 'invindex' must be supplied");        }        # now that we have an invindex, get a reader for it        $self->{reader} = KinoSearch::Index::IndexReader->new(            invindex => $self->{invindex} );    }}my %search_args = (    query    => undef,    filter   => undef,    num_docs => undef,);sub search {    my $self = shift;    my %args =        @_ == 1        ? ( %search_args, query => $_[0] )        : ( %search_args, @_ );    confess kerror() unless verify_args( \%search_args, %args );    # turn a query string into a query against all fields    if ( !a_isa_b( $args{query}, 'KinoSearch::Search::Query' ) ) {        $args{query} = $self->_prepare_simple_search( $args{query} );    }    return KinoSearch::Search::Hits->new( searcher => $self, %args );}sub get_field_names {    my $self = shift;    return $self->{reader}->get_field_names(@_);}# Search for the query string against all indexed fieldssub _prepare_simple_search {    my ( $self, $query_string ) = @_;    my $indexed_field_names = $self->get_field_names( indexed => 1 );    my $query_parser = KinoSearch::QueryParser::QueryParser->new(        fields   => $indexed_field_names,        analyzer => $self->{analyzer},    );    return $query_parser->parse($query_string);}my %search_hit_collector_args = (    hit_collector => undef,    weight        => undef,    filter        => undef,    sort_spec     => undef,);sub search_hit_collector {    my $self = shift;    confess kerror() unless verify_args( \%search_hit_collector_args, @_ );    my %args = ( %search_hit_collector_args, @_ );    # wrap the collector if there's a filter    my $collector = $args{hit_collector};    if ( defined $args{filter} ) {        $collector = KinoSearch::Search::FilteredCollector->new(            filter_bits   => $args{filter}->bits($self),            hit_collector => $args{hit_collector},        );    }    # accumulate hits into the HitCollector if the query is valid    my $scorer = $args{weight}->scorer( $self->{reader} );    if ( defined $scorer ) {        $scorer->score_batch(            hit_collector => $collector,            end           => $self->{reader}->max_doc,        );    }}sub fetch_doc { $_[0]->{reader}->fetch_doc( $_[1] ) }sub max_doc   { shift->{reader}->max_doc }sub doc_freq {    my ( $self, $term ) = @_;    return $self->{reader}->doc_freq($term);}sub create_weight {    my ( $self, $query ) = @_;    return $query->to_weight($self);}sub rewrite {    my ( $self, $query ) = @_;    my $reader = $self->{reader};    while (1) {        my $rewritten = $query->rewrite($reader);        last if ( 0 + $rewritten == 0 + $query );        $query = $rewritten;    }    return $query;}sub close {    my $self = shift;    $self->{reader}->close if $self->{close_reader};}1;__END__=head1 NAMEKinoSearch::Searcher - execute searches=head1 SYNOPSIS    my $analyzer = KinoSearch::Analysis::PolyAnalyzer->new(         language => 'en',    );    my $searcher = KinoSearch::Searcher->new(        invindex => $invindex,        analyzer => $analyzer,    );    my $hits = $searcher->search( query => 'foo bar' );=head1 DESCRIPTIONUse the Searcher class to perform queries against an invindex.  =head1 METHODS=head2 new    my $searcher = KinoSearch::Searcher->new(        invindex => $invindex,        analyzer => $analyzer,    );Constructor.  Takes two labeled parameters, both of which are required.=over=item *B<invindex> - can be either a path to an invindex, or aL<KinoSearch::Store::InvIndex|KinoSearch::Store::InvIndex> object.=item *B<analyzer> - An object which subclassesL<KinoSearch::Analysis::Analyer|KinoSearch::Analysis::Analyzer>, such as aL<PolyAnalyzer|KinoSearch::Analysis::PolyAnalyzer>.  This B<must> be identicalto the Analyzer used at index-time, or the results won't match up.=back=head2 search    my $hits = $searcher->search(         query  => $query,  # required        filter => $filter, # default: undef (no filtering)    );Process a search and return a L<Hits|KinoSearch::Search::Hits> object.search() expects labeled hash-style parameters.=over=item *B<query> - Can be either an object which subclassesL<KinoSearch::Search::Query|KinoSearch::Search::Query>, or a query string.  Ifit's a query string, it will be parsed using a QueryParser and a search willbe performed against all indexed fields in the invindex.  For more sophisticatedsearching, supply Query objects, such as TermQuery and BooleanQuery.=item *B<filter> - Must be aL<KinoSearch::Search::QueryFilter|KinoSearch::Search::QueryFilter>.  Searchresults will be limited to only those documents which pass through the filter.=back=head1 Caching a SearcherWhen a Searcher is created, a small portion of the invindex is loaded intomemory.  For large document collections, this startup time may becomenoticable, in which case reusing the searcher is likely to speed up yoursearch application.  Caching a Searcher is especially helpful when running ahigh-activity app under mod_perl.Searcher objects always represent a snapshot of an invindex as it existed whenthe Searcher was created.  If you want the search results to reflectmodifications to an invindex, you must create a new Searcher after the updateprocess completes.=head1 COPYRIGHTCopyright 2005-2007 Marvin Humphrey=head1 LICENSE, DISCLAIMER, BUGS, etc.See L<KinoSearch|KinoSearch> version 0.163.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -