File Coverage

blib/lib/Catmandu/Store/ElasticSearch/Searcher.pm
Criterion Covered Total %
statement 9 68 13.2
branch 0 24 0.0
condition 0 16 0.0
subroutine 3 9 33.3
pod 0 3 0.0
total 12 120 10.0


line stmt bran cond sub pod time code
1             package Catmandu::Store::ElasticSearch::Searcher;
2              
3 1     1   6 use Catmandu::Sane;
  1         2  
  1         6  
4              
5             our $VERSION = '1.0201';
6              
7 1     1   152 use Moo;
  1         2  
  1         5  
8 1     1   281 use namespace::clean;
  1         2  
  1         5  
9              
10             with 'Catmandu::Iterable';
11              
12             has bag => (is => 'ro', required => 1);
13             has query => (is => 'ro', required => 1);
14             has start => (is => 'ro', required => 1);
15             has limit => (is => 'ro', required => 1);
16             has total => (is => 'ro');
17             has sort => (is => 'ro');
18              
19             sub _paging_generator {
20 0     0     my ($self) = @_;
21 0           my $es = $self->bag->store->es;
22 0           my $id_key = $self->bag->id_key;
23 0           my $index = $self->bag->index;
24 0           my $type = $self->bag->type;
25 0           my $query = $self->query;
26 0           my $sort = $self->sort;
27              
28             sub {
29 0     0     state $start = $self->start;
30 0           state $total = $self->total;
31 0           state $limit = $self->limit;
32 0           state $hits;
33 0 0         if (defined $total) {
34 0 0         return unless $total;
35             }
36 0 0 0       unless ($hits && @$hits) {
37 0 0 0       if ($total && $limit > $total) {
38 0           $limit = $total;
39             }
40 0           my $body = {query => $query, from => $start, size => $limit,};
41 0 0         $body->{sort} = $sort if defined $sort;
42 0           my $res
43             = $es->search(index => $index, type => $type, body => $body,);
44              
45 0           $hits = $res->{hits}{hits};
46 0           $start += $limit;
47             }
48 0 0         if ($total) {
49 0           $total--;
50             }
51 0   0       my $doc = shift(@$hits) || return;
52 0           my $data = $doc->{_source};
53 0           $data->{$id_key} = $doc->{_id};
54 0           $data;
55 0           };
56             }
57              
58             sub generator {
59 0     0 0   my ($self) = @_;
60              
61             # scroll + from isn't supported in es > 1.2
62 0 0         if ($self->start) {
63 0           return $self->_paging_generator;
64             }
65              
66 0           my $bag = $self->bag;
67 0           my $store = $bag->store;
68 0           my $id_key = $bag->id_key;
69             sub {
70 0     0     state $total = $self->total;
71 0 0         if (defined $total) {
72 0 0         return unless $total;
73             }
74              
75 0           state $scroll = do {
76 0           my $body = {query => $self->query};
77 0 0         $body->{sort} = $self->sort if $self->sort;
78 0           my %args = (
79             index => $bag->index,
80             type => $bag->type,
81             size => $bag->buffer_size, # TODO divide by number of shards
82             body => $body,
83             );
84 0 0 0       if (!$self->sort && $store->is_es_1_or_2) {
85 0           $args{search_type} = 'scan';
86             }
87 0           $store->es->scroll_helper(%args);
88             };
89              
90 0   0       my $doc = $scroll->next // do {
91 0           $scroll->finish;
92 0           return;
93             };
94 0 0         if ($total) {
95 0           $total--;
96             }
97 0           my $data = $doc->{_source};
98 0           $data->{$id_key} = $doc->{_id};
99 0           $data;
100 0           };
101             }
102              
103             sub slice { # TODO constrain total?
104 0     0 0   my ($self, $start, $total) = @_;
105 0   0       $start //= 0;
106 0           $self->new(
107             bag => $self->bag,
108             query => $self->query,
109             start => $self->start + $start,
110             limit => $self->limit,
111             total => $total,
112             sort => $self->sort,
113             );
114             }
115              
116             sub count {
117 0     0 0   my ($self) = @_;
118 0           my $bag = $self->bag;
119             $bag->store->es->count(
120             index => $bag->index,
121             type => $bag->type,
122             body => {query => $self->query,},
123 0           )->{count};
124             }
125              
126             1;
127              
128             __END__
129              
130             =pod
131              
132             =head1 NAME
133              
134             Catmandu::Store::ElasticSearch::Bag - Searcher implementation for Elasticsearch
135              
136             =head1 DESCRIPTION
137              
138             This class isn't normally used directly. Instances are constructed using the store's C<searcher> method.
139              
140             =head1 SEE ALSO
141              
142             L<Catmandu::Iterable>
143              
144             =cut