File Coverage

blib/lib/Elastic/Model/Role/Store.pm
Criterion Covered Total %
statement 9 119 7.5
branch 0 14 0.0
condition 0 6 0.0
subroutine 3 34 8.8
pod 25 25 100.0
total 37 198 18.6


line stmt bran cond sub pod time code
1             package Elastic::Model::Role::Store;
2             $Elastic::Model::Role::Store::VERSION = '0.52';
3 3     3   71563 use Moose::Role;
  3         968403  
  3         18  
4              
5 3     3   16191 use Elastic::Model::Types qw(ES);
  3         11  
  3         26  
6 3     3   19788 use namespace::autoclean;
  3         7  
  3         24  
7              
8             #===================================
9             has 'es' => (
10             #===================================
11                 isa => ES,
12                 is => 'ro',
13                 required => 1,
14             );
15              
16             my @Top_Level = qw(
17             index type lenient
18             preference routing scroll
19             search_type timeout version
20             );
21              
22             #===================================
23             sub search {
24             #===================================
25 0     0 1       my $self = shift;
26 0               my $args = _tidy_search(@_);
27 0               $self->es->search($args);
28             }
29              
30             #===================================
31             sub scrolled_search {
32             #===================================
33 0     0 1       my $self = shift;
34 0               my $args = _tidy_search(@_);
35 0               $self->es->scroll_helper($args);
36             }
37              
38             #===================================
39             sub _tidy_search {
40             #===================================
41 0 0   0         my %body = ref $_[0] eq 'HASH' ? %{ shift() } : @_;
  0            
42 0               my %args;
43 0               for (@Top_Level) {
44 0                   my $val = delete $body{$_};
45 0 0                 if ( defined $val ) {
46 0                       $args{$_} = $val;
47                     }
48                 }
49 0               $args{body} = \%body;
50 0               return \%args;
51             }
52             #===================================
53             sub delete_by_query {
54             #===================================
55 0     0 1       my $self = shift;
56 0               my $args = _tidy_search(@_);
57 0               $self->es->delete_by_query($args);
58             }
59              
60             #===================================
61             sub get_doc {
62             #===================================
63 0     0 1       my ( $self, $uid, %args ) = @_;
64                 return $self->es->get(
65                     fields => [qw(_routing _parent)],
66                     _source => 1,
67 0                   %{ $uid->read_params },
  0            
68                     %args,
69                 );
70             }
71              
72             #===================================
73             sub doc_exists {
74             #===================================
75 0     0 1       my ( $self, $uid, %args ) = @_;
76 0               return !!$self->es->exists( %{ $uid->read_params }, %args, );
  0            
77             }
78              
79             #===================================
80 0     0 1   sub create_doc { shift->_write_doc( 'create', @_ ) }
81 0     0 1   sub index_doc { shift->_write_doc( 'index', @_ ) }
82             #===================================
83              
84             #===================================
85             sub _write_doc {
86             #===================================
87 0     0         my ( $self, $action, $uid, $data, %args ) = @_;
88                 return $self->es->$action(
89                     body => $data,
90 0                   %{ $uid->write_params },
  0            
91                     %args
92                 );
93             }
94              
95             #===================================
96             sub delete_doc {
97             #===================================
98 0     0 1       my $self = shift;
99 0               my $uid = shift;
100 0               my %args = _cleanup(@_);
101 0               return $self->es->delete( %{ $uid->write_params }, %args );
  0            
102             }
103              
104             #===================================
105             sub bulk {
106             #===================================
107 0     0 1       my ( $self, %args ) = @_;
108 0               return $self->es->bulk(%args);
109             }
110              
111             #===================================
112             sub index_exists {
113             #===================================
114 0     0 1       my ( $self, %args ) = @_;
115 0               return $self->es->indices->exists(%args);
116             }
117              
118             #===================================
119             sub create_index {
120             #===================================
121 0     0 1       my ( $self, %args ) = @_;
122                 $args{body} = {
123                     settings => ( delete( $args{settings} ) || {} ),
124 0   0               mappings => ( delete( $args{mappings} ) || {} ),
      0        
125                 };
126 0               return $self->es->indices->create(%args);
127             }
128              
129             #===================================
130             sub delete_index {
131             #===================================
132 0     0 1       my $self = shift;
133 0               my %args = _cleanup(@_);
134 0               return $self->es->indices->delete(%args);
135             }
136              
137             #===================================
138             sub refresh_index {
139             #===================================
140 0     0 1       my $self = shift;
141 0               my %args = _cleanup(@_);
142 0               return $self->es->indices->refresh(%args);
143             }
144              
145             #===================================
146             sub open_index {
147             #===================================
148 0     0 1       my $self = shift;
149 0               my %args = _cleanup(@_);
150 0               return $self->es->indices->open(%args);
151             }
152              
153             #===================================
154             sub close_index {
155             #===================================
156 0     0 1       my $self = shift;
157 0               my %args = _cleanup(@_);
158 0               return $self->es->indices->close(%args);
159             }
160              
161             #===================================
162             sub update_index_settings {
163             #===================================
164 0     0 1       my ( $self, %args ) = @_;
165 0               $args{body} = { settings => delete $args{settings} };
166 0               return $self->es->indices->put_settings(%args);
167             }
168              
169             #===================================
170             sub get_aliases {
171             #===================================
172 0     0 1       my $self = shift;
173 0               my %args = _cleanup(@_);
174 0   0           return $self->es->indices->get_aliases( ignore => 404, %args ) || {};
175             }
176              
177             #===================================
178             sub put_aliases {
179             #===================================
180 0     0 1       my ( $self, %args ) = @_;
181 0               $args{body} = { actions => delete $args{actions} };
182 0               return $self->es->indices->update_aliases(%args);
183             }
184              
185             #===================================
186             sub get_mapping {
187             #===================================
188 0     0 1       my $self = shift;
189 0               my %args = _cleanup(@_);
190 0               return $self->es->indices->get_mapping(%args);
191             }
192              
193             #===================================
194             sub put_mapping {
195             #===================================
196 0     0 1       my ( $self, %args ) = @_;
197 0               $args{body} = delete $args{mapping};
198 0               return $self->es->indices->put_mapping(%args);
199             }
200              
201             #===================================
202             sub delete_mapping {
203             #===================================
204 0     0 1       my $self = shift;
205 0               my %args = _cleanup(@_);
206 0               return $self->es->indices->delete_mapping(%args);
207             }
208              
209             #===================================
210             sub reindex {
211             #===================================
212 0     0 1       my ( $self, %args ) = @_;
213                 my %params = (
214                     max_count => delete $args{bulk_size},
215                     on_conflict => delete $args{on_conflict},
216                     on_error => delete $args{on_error},
217                     verbose => delete $args{verbose},
218 0               );
219 0               for ( keys %params ) {
220 0 0                 delete $params{$_} unless defined $params{$_};
221                 }
222 0               my $bulk = $self->es->bulk_helper(%params);
223 0               $bulk->reindex( %args, version_type => 'external', );
224             }
225              
226             #===================================
227             sub bootstrap_uniques {
228             #===================================
229 0     0 1       my ( $self, %args ) = @_;
230              
231 0               my $es = $self->es;
232 0 0             return if $es->indices->exists( index => $args{index} );
233              
234                 $es->indices->create(
235                     index => $args{index},
236 0                   body => {
237                         settings => { number_of_shards => 1 },
238                         mappings => {
239                             _default_ => {
240                                 _all => { enabled => 0 },
241                                 _source => { enabled => 0 },
242                                 _type => { index => 'no' },
243                                 enabled => 0,
244                             }
245                         }
246                     }
247                 );
248             }
249              
250             #===================================
251             sub create_unique_keys {
252             #===================================
253 0     0 1       my ( $self, %args ) = @_;
254 0               my %keys = %{ $args{keys} };
  0            
255              
256 0               my %failed;
257                 my $bulk = $self->es->bulk_helper(
258                     index => $args{index},
259                     on_conflict => sub {
260 0     0                 my ( $action, $doc ) = @_;
261 0                       $failed{ $doc->{_type} } = $doc->{_id};
262                     },
263                     on_error => sub {
264 0     0                 die "Error creating multi unique keys: $_[2]";
265                     }
266 0               );
267                 $bulk->create(
268 0                   map { +{ _type => $_, _id => $keys{$_}, _source => {} } }
  0            
269                         keys %keys
270                 );
271 0               $bulk->flush;
272 0 0             if (%failed) {
273 0                   delete @keys{ keys %failed };
274 0                   $self->delete_unique_keys( index => $args{index}, keys => \%keys );
275                 }
276 0               return %failed;
277             }
278              
279             #===================================
280             sub delete_unique_keys {
281             #===================================
282 0     0 1       my ( $self, %args ) = @_;
283 0               my %keys = %{ $args{keys} };
  0            
284              
285                 my $bulk = $self->es->bulk_helper(
286                     index => $args{index},
287                     on_error => sub {
288 0     0                 die "Error deleting multi unique keys: $_[2]";
289                     }
290 0               );
291 0               $bulk->delete( map { { type => $_, id => $keys{$_} } } keys %keys );
  0            
292 0               $bulk->flush;
293 0               return 1;
294             }
295              
296             our %Warned;
297              
298             #===================================
299             sub _cleanup {
300             #===================================
301 0     0         my (%args) = @_;
302 0 0             if ( delete $args{ignore_missing} ) {
303                     warn "(ignore_missing) is deprecated. use { ignore => 404 } instead"
304 0 0                     unless $Warned{ignore_missing}++;
305 0                   $args{ignore} = 404;
306                 }
307 0               return (%args);
308             }
309              
310             1;
311              
312             =pod
313            
314             =encoding UTF-8
315            
316             =head1 NAME
317            
318             Elastic::Model::Role::Store - Elasticsearch backend for document read/write requests
319            
320             =head1 VERSION
321            
322             version 0.52
323            
324             =head1 DESCRIPTION
325            
326             All document-related requests to the Elasticsearch backend are handled
327             via L<Elastic::Model::Role::Store>.
328            
329             =head1 ATTRIBUTES
330            
331             =head2 es
332            
333             $es = $store->es
334            
335             Returns the connection to Elasticsearch.
336            
337             =head1 METHODS
338            
339             =head2 get_doc()
340            
341             $result = $store->get_doc($uid, %args);
342            
343             Retrieves the doc specified by the L<$uid|Elastic::Model::UID> from
344             Elasticsearch, by calling L<Search::Elasticsearch/"get()">. Throws an exception
345             if the document does not exist.
346            
347             =head2 doc_exists()
348            
349             $bool = $store->doc_exists($uid, %args);
350            
351             Checks whether the doc exists in ElastciSearch. Any C<%args> are passed through
352             to L<Search::Elasticsearch/exists()>.
353            
354             =head2 create_doc()
355            
356             $result = $store->create_doc($uid => \%data, %args);
357            
358             Creates a doc in the Elasticsearch backend and returns the raw result.
359             Throws an exception if a doc with the same L<$uid|Elastic::Model::UID>
360             already exists. Any C<%args> are passed to L<Search::Elasticsearch::Client::Direct/"create()">
361            
362             =head2 index_doc()
363            
364             $result = $store->index_doc($uid => \%data, %args);
365            
366             Updates (or creates) a doc in the Elasticsearch backend and returns the raw
367             result. Any failure throws an exception. If the L<version|Elastic::Model::UID/"version">
368             number does not match what is stored in Elasticsearch, then a conflict exception
369             will be thrown. Any C<%args> will be passed to L<Search::Elasticsearch::Client::Direct/"index()">.
370             For instance, to overwrite a document regardless of version number, you could
371             do:
372            
373             $result = $store->index_doc($uid => \%data, version => 0 );
374            
375             =head2 delete_doc()
376            
377             $result = $store->delete_doc($uid, %args);
378            
379             Deletes a doc in the Elasticsearch backend and returns the raw
380             result. Any failure throws an exception. If the L<version|Elastic::Model::UID/"version">
381             number does not match what is stored in Elasticsearch, then a conflict exception
382             will be thrown. Any C<%args> will be passed to L<Search::Elasticsearch::Client::Direct/"delete()">.
383            
384             =head2 bulk()
385            
386             $result = $store->bulk(
387             actions => $actions,
388             on_conflict => sub {...},
389             on_error => sub {...},
390             on_success => sub {...},
391             %args
392             );
393            
394             Performs several actions in a single request. Any %args will be passed to
395             L<Search::Elasticsearch::Client::Direct/bulk_helper()>.
396            
397             =head2 search()
398            
399             $results = $store->search(@args);
400            
401             Performs a search, passing C<@args> to L<Search::Elasticsearch::Client::Direct/"search()">.
402            
403             =head2 scrolled_search()
404            
405             $results = $store->scrolled_search(@args);
406            
407             Performs a scrolled search, passing C<@args> to L<Search::Elasticsearch::Client::Direct/"scroll_helper()">.
408            
409             =head2 delete_by_query()
410            
411             $response = $store->delete_by_query(@args);
412            
413             Performs a delete-by-query, passing C<@args> to L<Search::Elasticsearch::Client::Direct/delete_by_query()>.
414            
415             =head2 index_exists()
416            
417             $bool = $store->index_exists(@args);
418            
419             Checks whether the specified index exists, passing C<@args> to L<Search::Elasticsearch::Client::Direct::Indices/exists()>.
420            
421             =head2 create_index()
422            
423             $response = $store->create_index(@args);
424            
425             Creates the specified index, passing C<@args> to L<Search::Elasticsearch::Client::Direct::Indices/create()>.
426            
427             =head2 delete_index()
428            
429             $response = $store->delete_index(@args);
430            
431             Deletes the specified index, passing C<@args> to L<Search::Elasticsearch::Client::Direct::Indices/delete()>.
432            
433             =head2 refresh_index()
434            
435             $response = $store->refresh_index(@args);
436            
437             Refreshes the specified index, passing C<@args> to L<Search::Elasticsearch::Client::Direct::Indices/refresh()>.
438            
439             =head2 open_index()
440            
441             $response = $store->open_index(@args);
442            
443             Opens the specified index, passing C<@args> to L<Search::Elasticsearch::Client::Direct::Indices/open()>.
444            
445             =head2 close_index()
446            
447             $response = $store->close_index(@args);
448            
449             Closes the specified index, passing C<@args> to L<Search::Elasticsearch::Client::Direct::Indices/close()>.
450            
451             =head2 update_index_settings()
452            
453             $response = $store->update_index_settings(@args);
454            
455             Updates the settings of the specified index, passing C<@args> to L<Search::Elasticsearch::Client::Direct::Indices/update_settings()>.
456            
457             =head2 get_aliases()
458            
459             $response = $store->get_aliases(@args);
460            
461             Retrieves the aliases for the specified indices, passing C<@args> to L<Search::Elasticsearch::Client::Direct::Indices/get_aliases()>.
462            
463             =head2 put_aliases()
464            
465             $response = $store->put_aliases(@args);
466            
467             Updates the aliases for the specified indices, passing C<@args> to L<Search::Elasticsearch::Client::Direct::Indices/update_aliases()>.
468            
469             =head2 get_mapping()
470            
471             $response = $store->get_mapping(@args);
472            
473             Retrieves the mappings for the specified index, passing C<@args> to L<Search::Elasticsearch::Client::Direct::Indices/get_mapping()>.
474            
475             =head2 put_mapping()
476            
477             $response = $store->put_mapping(@args);
478            
479             Updates the mappings for the specified index, passing C<@args> to L<Search::Elasticsearch::Client::Direct::Indices/put_mapping()>.
480            
481             =head2 delete_mapping()
482            
483             $response = $store->delete_mapping(@args);
484            
485             Deletes the mappings and associated documents for the specified index, passing C<@args> to L<Search::Elasticsearch::Client::Direct::Indices/delete_mapping()>.
486            
487             =head2 reindex()
488            
489             $response = $store->reindex(@args);
490            
491             Passes the C<@args> to L<Search::Elasticsearch::Bulk/reindex()>.
492            
493             =head2 bootstrap_uniques()
494            
495             $response = $store->bootstrap_uniques(@args);
496            
497             Creates the index which will store unique constraints, unless it already exists.
498            
499             =head2 create_unique_keys()
500            
501             $response = $store->create_unique_keys(@args);
502            
503             Inserts the documents representing unique constraints, and throws an error if they already exist.
504            
505             =head2 delete_unique_keys()
506            
507             $response = $store->delete_unique_keys(@args);
508            
509             Deletes the documents representing the specified unique constraints.
510            
511             =head1 AUTHOR
512            
513             Clinton Gormley <drtech@cpan.org>
514            
515             =head1 COPYRIGHT AND LICENSE
516            
517             This software is copyright (c) 2015 by Clinton Gormley.
518            
519             This is free software; you can redistribute it and/or modify it under
520             the same terms as the Perl 5 programming language system itself.
521            
522             =cut
523              
524             __END__
525            
526             # ABSTRACT: Elasticsearch backend for document read/write requests
527            
528