📄 booleanscorer.pm
字号:
package Plucene::Search::BooleanScorer;=head1 NAME Plucene::Search::BooleanScorer - A boolean scorer=head1 SYNOPSIS # isa Plucene::Search::Scorer $bool_scorer->add($scorer, $required, $prohibited); $bool_scorer->score($results, $max_doc);=head1 DESCRIPTIONThis is a scoring class for boolean scorers.=head1 METHODS=cutuse strict;use warnings;use List::Util qw(min);use Plucene::Search::Similarity;use base qw(Plucene::Search::Scorer Class::Accessor::Fast);__PACKAGE__->mk_accessors( qw(next_mask required_mask prohibited_mask max_coord scorers bucket_table coord_factors current_doc));=head2 new my $bool_scorer = Plucene::Search::BooleanScorer->new;Create a new Plucene::Search::BooleanScorer object.=head2 next_mask / required_mask / prohibited_mask max_coord / scorers / bucket_table / coord_factors / current_docGet / set these attributes=cutsub new { my $self = shift->SUPER::new(@_); $self->max_coord(1); $self->next_mask(1); $self->current_doc(0); $self->required_mask(0); $self->prohibited_mask(0); $self->scorers([]); $self->bucket_table(Plucene::Search::BucketTable->new({ scorer => $self })); return $self;}=head2 add $bool_scorer->add($scorer, $required, $prohibited);=cutsub add { my ($self, $scorer, $required, $prohibited) = @_; my $mask = 0; if ($required || $prohibited) { $mask = $self->next_mask; $self->{next_mask} <<= 1; } $self->{max_coord}++ unless $prohibited; $self->{prohibited_mask} |= $mask if $prohibited; $self->{required_mask} |= $mask if $required; push @{ $self->{scorers} }, { scorer => $scorer, required => $required, prohibited => $prohibited, collector => $self->bucket_table->new_collector($mask) };}sub _compute_coord_factors { my $self = shift; $self->coord_factors([ map Plucene::Search::Similarity->coord($_, $self->max_coord), 0 .. $self->max_coord ]);}=head2 score $bool_scorer->score($results, $max_doc);=cutsub score { my ($self, $results, $max_doc) = @_; $self->_compute_coord_factors if not defined $self->coord_factors; while ($self->current_doc < $max_doc) { $self->current_doc( min( $self->{current_doc} + $Plucene::Search::BucketTable::SIZE, $max_doc )); for my $t (@{ $self->{scorers} }) { $t->{scorer}->score($t->{collector}, $self->current_doc); } $self->bucket_table->collect_hits($results); }}package Plucene::Search::BucketTable;our $SIZE = 1 << 10;our $MASK = $SIZE - 1;use base 'Class::Accessor::Fast';__PACKAGE__->mk_accessors(qw(buckets first scorer));sub new { my $self = shift->SUPER::new(@_); $self->buckets([]); $self;}sub collect_hits { my ($self, $results) = @_; my $scorer = $self->scorer; my $required = $scorer->required_mask; my $prohibited = $scorer->prohibited_mask; my @coord = @{ $scorer->coord_factors }; for (my $bucket = $self->{first} ; $bucket ; $bucket = $bucket->{next}) { if ( ($bucket->{bits} & $prohibited) == 0 and ($bucket->{bits} & $required) == $required) { $results->collect($bucket->{doc}, $bucket->{score} * $coord[ $bucket->{coord} ]); } } undef $self->{first};}sub new_collector { my ($self, $mask) = @_; return Plucene::Search::BucketCollector->new({ bucket_table => $self, mask => $mask });}package Plucene::Search::BucketCollector;use base (qw(Class::Accessor::Fast Plucene::Search::HitCollector));__PACKAGE__->mk_accessors(qw(bucket_table mask));sub collect { my ($self, $doc, $score) = @_; my $table = $self->{bucket_table}; my $i = $doc & $Plucene::Search::BucketTable::MASK; my $bucket = $table->buckets->[$i]; $table->buckets->[$i] = $bucket = {} unless $bucket; if (not defined $bucket->{doc} or $bucket->{doc} != $doc) { @{$bucket}{qw(doc score bits coord)} = ($doc, $score, $self->{mask}, 1); $bucket->{next} = $table->first; $table->first($bucket); } else { $bucket->{score} += $score; $bucket->{bits} |= $self->{mask}; $bucket->{coord}++; }}1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -