File Coverage

blib/lib/Plucene/Search/BooleanQuery.pm
Criterion Covered Total %
statement 53 54 98.1
branch 10 14 71.4
condition 2 4 50.0
subroutine 14 14 100.0
pod 7 7 100.0
total 86 93 92.4


line stmt bran cond sub pod time code
1             package Plucene::Search::BooleanQuery;
2              
3             =head1 NAME
4              
5             Plucene::Search::BooleanQuery - a boolean query
6              
7             =head1 SYNOPSIS
8              
9             # isa Plucene::Search::Query
10              
11             $query->add(Plucene::Search::Query $query, $required, $prohibited);
12             $query->normalize($norm);
13            
14             my @clauses = $query->clauses;
15             my $sum_sq_weights = $query->sum_squared_weights($searcher);
16             my $as_string = $query->to_string($field);
17            
18             =head1 DESCRIPTION
19              
20             A query that matches documents matching boolean combinations of
21             other queries, typically TermQuerys or PhraseQuery
22              
23             A boolean query represents a composite query that may contains subqueries
24             of arbitrary nesting level and with composition rules such as 'and',
25             'or' or 'not'.
26              
27             Boolean queries are represented in Plucene API by instances of the
28             BooleanQuery class. Each BooleanQuery object contains a list of subqueries
29             that are linked using instances of the adaptor class BooleanClause. The
30             subqueries may be of any Query type such as term query, phrase query and
31             nested boolean queries.
32              
33             Each sub query of a boolean query has two binary qualifiers that controls
34             how its super query is matched. These qualifiers are
35              
36             =over 4
37              
38             =item * prohibited - when this flag is set, the matching status of the
39             subquery is negated such that the query is considered as a match only
40             when the sub query does not match.
41            
42             =item * required - when this flag is set, the sub query is required to match
43             (or not to match if its 'prohibited' flag is set) for the super query
44             to match. This this is a necessary but not sufficient condition for the
45             super query to match.
46              
47             =back
48              
49             =head1 METHODS
50              
51             =cut
52              
53 3     3   18 use strict;
  3         6  
  3         104  
54 3     3   14 use warnings;
  3         8  
  3         78  
55              
56 3     3   17 use List::Util qw(sum);
  3         5  
  3         218  
57              
58 3     3   16 use Plucene::Search::BooleanClause;
  3         8  
  3         38  
59 3     3   1694 use Plucene::Search::BooleanScorer;
  3         9  
  3         34  
60              
61 3     3   91 use base "Plucene::Search::Query";
  3         6  
  3         1877  
62              
63             __PACKAGE__->mk_accessors(qw(clauses));
64              
65             =head2 add
66              
67             $query->add(Plucene::Search::Query $query, $required, $prohibited);
68              
69             Adds a clause to a boolean query. Clauses may be:
70              
71             =over
72              
73             =item required
74              
75             which means that documents which I match this sub-query will
76             I match the boolean query;
77              
78             =item prohibited
79              
80             which means that documents which I match this sub-query will I match
81             the boolean query; or
82              
83             =item
84              
85             neither, in which case matched documents are neither prohibited from
86             nor required to match the sub-query.
87              
88             =back
89              
90             It is an error to specify a clause as both required and prohibited.
91              
92             =cut
93              
94             sub add {
95 3     3 1 9 my ($self, $query, $required, $prohibited) = @_;
96 3   50     4 push @{ $self->{clauses} },
  3   50     52  
97             Plucene::Search::BooleanClause->new({
98             query => $query,
99             required => ($required || 0),
100             prohibited => ($prohibited || 0) });
101             }
102              
103             =head2 add_clause
104              
105             $self->add_clause(Plucene::Search::BooleanClause $c);
106            
107             Adds an already-formed clause onto the query.
108              
109             =cut
110              
111             sub add_clause {
112 69     69 1 103 my ($self, $clause) = @_;
113 69         82 push @{ $self->{clauses} }, $clause;
  69         321  
114             }
115              
116             =head2 clauses
117              
118             my @clauses = $query->clauses;
119              
120             =cut
121              
122 101     101 1 135 sub clauses { @{ shift->{clauses} } }
  101         470  
123              
124             sub prepare {
125 15     15 1 45 my ($self, $reader) = @_;
126 15         59 $_->query->prepare($reader) for $self->clauses;
127             }
128              
129             =head2 sum_squared_weights
130              
131             my $sum_sq_weights = $query->sum_squared_weights($searcher);
132              
133             =cut
134              
135             sub sum_squared_weights {
136 16     16 1 65 my ($self, $searcher) = @_;
137 16         61 sum map $_->query->sum_squared_weights($searcher), grep !$_->prohibited,
138             $self->clauses;
139             }
140              
141             =head2 normalize
142              
143             $query->normalize($norm);
144              
145             =cut
146              
147             sub normalize {
148 16     16 1 79 my ($self, $norm) = @_;
149 16         74 $_->query->normalize($norm) for grep !$_->prohibited, $self->clauses;
150             }
151              
152             sub _scorer {
153 16     16   68 my ($self, $reader) = @_;
154 16         51 my @clauses = $self->clauses;
155 16 100       66 if (@clauses == 1) {
156 1         3 my $c = $clauses[0];
157 1 50       5 return $c->query->_scorer($reader) unless $c->prohibited;
158             }
159              
160 16         169 my $result = Plucene::Search::BooleanScorer->new();
161 16         60 for my $c ($self->clauses) {
162 32         383 my $subscorer = $c->query->_scorer($reader);
163 32 50       148 if ($subscorer) {
164 32         145 $result->add($subscorer, $c->required, $c->prohibited);
165             } else {
166              
167             # If it was required and we didn't score, kill it.
168 0 0       0 return if $c->required;
169             }
170             }
171              
172 16         411 return $result;
173             }
174              
175             =head2 to_string
176              
177             my $as_string = $query->to_string($field);
178              
179             =cut
180              
181             sub to_string {
182 22     22 1 8519 my ($self, $field) = @_;
183 44         42 join " ", map {
184 22         58 my $buffer;
185 44 100       114 $buffer .= "-" if $_->prohibited;
186 44 100       313 $buffer .= "+" if $_->required;
187 44         254 my $q = $_->query;
188 44 100       333 if ($q->isa(__PACKAGE__)) {
189 4         13 $buffer .= "(" . $q->to_string($field) . ")";
190             } else {
191 40         109 $buffer .= $q->to_string($field);
192             }
193 44         170 $buffer;
194             } $self->clauses;
195             }
196              
197             1;