File Coverage

blib/lib/Catmandu/Store/ElasticSearch/Searcher.pm
Criterion Covered Total %
statement 9 78 11.5
branch 0 30 0.0
condition 0 16 0.0
subroutine 3 9 33.3
pod 0 3 0.0
total 12 136 8.8


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