File Coverage

blib/lib/KSx/Searcher/Abstract.pm
Criterion Covered Total %
statement 13 15 86.6
branch n/a
condition n/a
subroutine 5 5 100.0
pod n/a
total 18 20 90.0


line stmt bran cond sub pod time code
1 2     2   87608 use strict;
  2         6  
  2         86  
2 2     2   13 use warnings;
  2         5  
  2         135  
3              
4             package KSx::Searcher::Abstract;
5              
6             our $VERSION = '0.002';
7 2     2   56 use 5.008003; # KinoSearch requires this
  2         13  
  2         107  
8              
9 2     2   11 use base qw(KinoSearch::Searcher);
  2         5  
  2         1916  
10              
11 2     2   127243 use KinoSearch::Search::BooleanQuery;
  0            
  0            
12             use KinoSearch::Search::MatchFieldQuery;
13             use KinoSearch::Search::TermQuery;
14             use KinoSearch::Search::PolyFilter;
15             use KinoSearch::Search::RangeFilter;
16             # we should figure out a way to use this for better performance
17             #use aliased 'KinoSearch::Search::QueryFilter';
18             use KinoSearch::Search::SortSpec;
19             use KinoSearch::Index::Term;
20              
21             sub search {
22             my ($self, $query, $options) = @_;
23             unless ($query) {
24             Carp::croak "'query' argument is mandatory for search";
25             }
26             $options ||= {};
27             $self->SUPER::search(
28             $self->build_abstract($query, $options)
29             );
30             }
31              
32             sub _clause_is { shift; return query => _term(@_), occur => 'MUST' }
33             sub _clause_not { shift; return query => _term(@_), occur => 'MUST_NOT' }
34              
35             sub _term {
36             KinoSearch::Search::TermQuery->new(
37             term => KinoSearch::Index::Term->new(@_)
38             )
39             }
40              
41             sub _process_hash {
42             my ($self, $key, $val, $bq) = @_;
43             for my $k (keys %$val) {
44             if ($k eq '=') {
45             $bq->add_clause($self->_clause_is($key, $val));
46             } elsif ($k eq '!=') {
47             $bq->add_clause($self->_clause_not($key, $val));
48             } else {
49             die "unhandled operator: $k";
50             }
51             }
52             }
53              
54             sub build_abstract {
55             my ($self, $query, $options) = @_;
56            
57             Carp::croak "can't process empty query" unless %$query;
58             my $bq = KinoSearch::Search::BooleanQuery->new;
59            
60             # TODO: allow arrayref queries
61             for my $key (sort keys %$query) {
62             my $val = $query->{$key};
63             if (ref $val eq 'HASH') {
64             $self->_process_hash($key, $val, $bq);
65             } elsif (not ref $val) {
66             $bq->add_clause($self->_clause_is($key, $val));
67             } else {
68             Carp::croak "unhandled value: $val";
69             }
70             }
71              
72             my $sort_spec;
73             # XXX I hate this format. It is still too wordy. It should change.
74             if (my $sort = delete $options->{sort}) {
75             $sort_spec = KinoSearch::Search::SortSpec->new;
76             for (@$sort) { $sort_spec->add(%$_) }
77             }
78             return (
79             query => $bq,
80             # filter => ???
81             %$options,
82             $sort_spec ? (sort_spec => $sort_spec) : (),
83             )
84             }
85              
86             1;
87             __END__