File Coverage

blib/lib/Elastic/Model.pm
Criterion Covered Total %
statement 26 34 76.4
branch 6 16 37.5
condition 1 3 33.3
subroutine 11 13 84.6
pod 4 9 44.4
total 48 75 64.0


line stmt bran cond sub pod time code
1             package Elastic::Model;
2             $Elastic::Model::VERSION = '0.52';
3 23     23   4182516 use Moose 2.06 ();
  23         7785670  
  23         810  
4 23     23   224 use Moose::Exporter();
  23         55  
  23         425  
5 23     23   122 use Carp;
  23         52  
  23         1844  
6 23     23   21789 use namespace::autoclean;
  23         194804  
  23         138  
7              
8             Moose::Exporter->setup_import_methods(
9                 class_metaroles => { class => ['Elastic::Model::Meta::Class::Model'] },
10                 with_meta => [
11                     qw(has_namespace has_typemap override_classes
12             has_analyzer has_tokenizer has_filter has_char_filter
13             has_unique_index)
14                 ],
15                 also => 'Moose',
16             );
17              
18             #===================================
19             sub init_meta {
20             #===================================
21 23     23 0 2316     shift;
22 23         131     my $meta = Moose->init_meta(@_);
23 23         125224     Moose::Util::apply_all_roles( $meta, 'Elastic::Model::Role::Model' );
24             }
25              
26             #===================================
27             sub has_namespace {
28             #===================================
29 26     26 0 88188     my $meta = shift;
30 26 50       555     my $name = shift or croak "No namespace name passed to namespace";
31 26         236     my %params = ( types => @_ );
32              
33 26         76     my $types = $params{types};
34 26 50 33     331     croak "No types specified for namespace $name"
35                     unless $types && %$types;
36              
37 26         1728     $meta->add_namespace( $name => \%params );
38             }
39              
40             #===================================
41 11     11 0 733 sub has_typemap { shift->set_class( 'typemap', @_ ) }
42             #===================================
43              
44             #===================================
45             sub has_unique_index {
46             #===================================
47 0     0 0 0     my ( $meta, $val ) = @_;
48 0         0     $meta->unique_index($val);
49             }
50              
51             #===================================
52             sub override_classes {
53             #===================================
54 0     0 0 0     my $meta = shift;
55 0 0       0     my %classes = ref $_[0] eq 'HASH' ? %{ shift() } : @_;
  0         0  
56 0         0     for ( keys %classes ) {
57 0 0       0         croak "Unknown arg for classes ($_)"
58                         unless $meta->get_class($_);
59 0         0         $meta->set_class( $_ => $classes{$_} );
60                 }
61             }
62              
63             #===================================
64             sub has_analyzer {
65             #===================================
66 4 50   4 1 86     shift->add_analyzer( shift, ref $_[0] eq 'HASH' ? shift() : {@_} );
67             }
68             #===================================
69             sub has_tokenizer {
70             #===================================
71 1 50   1 1 21     shift->add_tokenizer( shift, ref $_[0] eq 'HASH' ? shift() : {@_} );
72             }
73             #===================================
74             sub has_filter {
75             #===================================
76 2 50   2 1 46     shift->add_filter( shift, ref $_[0] eq 'HASH' ? shift() : {@_} );
77             }
78              
79             #===================================
80             sub has_char_filter {
81             #===================================
82 1 50   1 1 24     shift->add_char_filter( shift, ref $_[0] eq 'HASH' ? shift() : {@_} );
83             }
84              
85             1;
86              
87             # ABSTRACT: A NoSQL document store with full text search for Moose objects using Elasticsearch as a backend.
88              
89             __END__
90            
91             =pod
92            
93             =encoding UTF-8
94            
95             =head1 NAME
96            
97             Elastic::Model - A NoSQL document store with full text search for Moose objects using Elasticsearch as a backend.
98            
99             =head1 VERSION
100            
101             version 0.52
102            
103             =head1 SYNOPSIS
104            
105             package MyApp;
106            
107             use Elastic::Model;
108            
109             has_namespace 'myapp' => {
110             user => 'MyApp::User',
111             post => 'MyApp::Post'
112             };
113            
114             has_typemap 'MyApp::TypeMap';
115            
116             # Setup custom analyzers
117            
118             has_filter 'edge_ngrams' => (
119             type => 'edge_ngram',
120             min_gram => 2,
121             max_gram => 10
122             );
123            
124             has_analyzer 'edge_ngrams' => (
125             tokenizer => 'standard',
126             filter => [ 'standard', 'lowercase', 'edge_ngrams' ]
127             );
128            
129             no Elastic::Model;
130            
131             =head1 DESCRIPTION
132            
133             Elastic::Model is a framework to store your Moose objects, which uses
134             Elasticsearch as a NoSQL document store and flexible search engine.
135            
136             It is designed to make it easy to start using Elasticsearch with minimal extra
137             code, but allows you full access to the rich feature set available in
138             Elasticsearch as soon as you are ready to use it.
139            
140             =head1 FUTURE OF ELASTIC::MODEL - PLEASE READ AND COMMENT
141            
142             Hi all users of Elastic::Model
143            
144             Elasticsearch 2.0.0 is out, and Elastic::Model doesn't support it.
145             In fact, Elastic::Model doesn't support a number of things from
146             Elasticsearch 1.x either. I apologise for neglecting this module.
147            
148             My feeling is that Elastic::Model tries to do way too much.
149             Like many frameworks, it ties you into doing things in a
150             particular way, which may or may not make sense for your use
151             case. Most people who use Elastic::Model seem to use a
152             subset of the functionality, and then talk to Elasticsearch
153             directly the rest of the time.
154            
155             I don't think it makes sense to just update the code for
156             2.x, it needs a complete rethink.
157            
158             =head2 TELL ME HOW YOU USE IT
159            
160             Please could you add comments to
161             L<this issue|https://github.com/clintongormley/Elastic-Model/issues/42>
162             explaining what bits you find useful, what bits you never use,
163             and what bits you find annoying. Perhaps the code can be split
164             out into smaller more useful chunks.
165            
166             =head1 INTRODUCTION TO Elastic::Model
167            
168             If you are not familiar with L<Elastic::Model>, you should start by reading
169             L<Elastic::Manual::Intro>.
170            
171             The rest of the documentation on this page explains how to use the
172             L<Elastic::Model> module itself.
173            
174             =head1 BACKWARDS COMPATIBILITY BREAK
175            
176             B<NOTE:> This version of Elastic::Model uses L<Search::Elasticsearch>
177             and is intended for Elasticsearch 1.x. However, it can be used
178             with Elasticsearch 0.90.x in "compatibility mode". Elasticsearch 2.x is
179             not supported.
180            
181             B<< You can no longer use the old L<Search::Elasticsearch::Compat>. >>
182             See L<Elastic::Manual::Delta> for instructions.
183            
184             For a version of Elastic::Model which uses Search::Elasticsearch::Compat
185             please see L<https://metacpan.org/release/DRTECH/Elastic-Model-0.28>.
186            
187             =head1 USING ELASTIC::MODEL
188            
189             Your application needs a C<model> class to handle the relationship between
190             your object classes and the Elasticsearch cluster.
191            
192             Your model class is most easily defined as follows:
193            
194             package MyApp;
195            
196             use Elastic::Model;
197            
198             has_namespace 'myapp' => {
199             user => 'MyApp::User',
200             post => 'MyApp::Post'
201             };
202            
203             no Elastic::Model;
204            
205             This applies L<Elastic::Model::Role::Model> to your C<MyApp> class,
206             L<Elastic::Model::Meta::Class::Model> to C<MyApp>'s metaclass and exports
207             functions which help you to configure your model.
208            
209             Your model must define at least one L<namespace|Elastic::Manual::Terminology/Namespace>,
210             which tells Elastic::Model which
211             L<type|Elastic::Manual::Terminology/Type> (like a table in a DB) should be
212             handled by which of your classes. So the above declaration says:
213            
214             I<"For all L<indices|Elastic::Model::Terminology/Index> which belong to namespace
215             C<myapp>, objects of class C<MyApp::User> will be stored under the
216             L<type|Elastic::Model::Terminology/Type> C<user> in Elasticsearch.">
217            
218             =head2 Custom TypeMap
219            
220             Elastic::Model uses a L<TypeMap|Elastic::Model::TypeMap::Default> to figure
221             out how to inflate and deflate your objects, and how to configure them
222             in Elasticsearch.
223            
224             You can specify your own TypeMap using:
225            
226             has_typemap 'MyApp::TypeMap';
227            
228             See L<Elastic::Model::TypeMap::Base> for instructions on how to define
229             your own type-map classes.
230            
231             =head2 Custom unique key index
232            
233             If you have attributes whose values are
234             L<unique|Elastic::Manual::Attributes::Unique>, then you can customize the index
235             where these unique values are stored.
236            
237             has_unique_index 'myapp_unique';
238            
239             The default value is C<unique_key>.
240            
241             =head2 Custom analyzers
242            
243             Analysis is the process of converting full text into C<terms> or C<tokens> and
244             is one of the things that gives full text search its power. When storing text
245             in the Elasticsearch index, the text is first analyzed into terms/tokens.
246             Then, when searching, search keywords go through the same analysis process
247             to produce the terms/tokens which are then searched for in the index.
248            
249             Choosing the right analyzer for each field gives you enormous control over
250             how your data can be queried.
251            
252             There are a large number of built-in analyzers available, but frequently
253             you will want to define custom analyzers, which consist of:
254            
255             =over
256            
257             =item *
258            
259             zero or more character filters
260            
261             =item *
262            
263             a tokenizer
264            
265             =item *
266            
267             zero or more token filters
268            
269             =back
270            
271             L<Elastic::Model> provides sugar to make it easy to specify custom analyzers:
272            
273             =head3 has_char_filter
274            
275             Character filters can change the text before it gets tokenized, for instance:
276            
277             has_char_filter 'my_mapping' => (
278             type => 'mapping',
279             mappings => ['ph=>f','qu=>q']
280             );
281            
282             See L<Elastic::Model::Meta::Class::Model/Default character filters> for a list
283             of the built-in character filters.
284            
285             =head3 has_tokenizer
286            
287             A tokenizer breaks up the text into individual tokens or terms. For instance,
288             the C<pattern> tokenizer could be used to split text using a regex:
289            
290             has_tokenizer 'my_word_tokenizer' => (
291             type => 'pattern',
292             pattern => '\W+', # splits on non-word chars
293             );
294            
295             See L<Elastic::Model::Meta::Class::Model/Default tokenizers> for a list
296             of the built-in tokenizers.
297            
298             =head3 has_filter
299            
300             Any terms/tokens produced by the L</"has_tokenizer"> can the be passed through
301             multiple token filters. For instance, each term could be broken down into
302             "edge ngrams" (eg 'foo' => 'f','fo','foo') for partial matching.
303            
304             has_filter 'my_ngrams' => (
305             type => 'edge_ngram',
306             min_gram => 1,
307             max_gram => 10,
308             );
309            
310             See L<Elastic::Model::Meta::Class::Model/Default token filters> for a list
311             of the built-in character token filters.
312            
313             =head3 has_analyzer
314            
315             Custom analyzers can be defined by combining character filters, a tokenizer and
316             token filters, some of which could be built-in, and some defined by the
317             keywords above.
318            
319             For instance:
320            
321             has_analyzer 'partial_word_analyzer' => (
322             type => 'custom',
323             char_filter => ['my_mapping'],
324             tokenizer => ['my_word_tokenizer'],
325             filter => ['lowercase','stop','my_ngrams']
326             );
327            
328             See L<Elastic::Model::Meta::Class::Model/Default analyzers> for a list
329             of the built-in analyzers.
330            
331             =head2 Overriding Core Classes
332            
333             If you would like to override any of the core classes used by L<Elastic::Model>,
334             then you can do so as follows:
335            
336             override_classes (
337             domain => 'MyApp::Domain',
338             store => 'MyApp::Store'
339             );
340            
341             The defaults are:
342            
343             =over
344            
345             =item *
346            
347             C<namespace> C<-----------> L<Elastic::Model::Namespace>
348            
349             =item *
350            
351             C<domain> C<--------------> L<Elastic::Model::Domain>
352            
353             =item *
354            
355             C<store> C<---------------> L<Elastic::Model::Store>
356            
357             =item *
358            
359             C<view> C<----------------> L<Elastic::Model::View>
360            
361             =item *
362            
363             C<scope> C<---------------> L<Elastic::Model::Scope>
364            
365             =item *
366            
367             C<results> C<-------------> L<Elastic::Model::Results>
368            
369             =item *
370            
371             C<cached_results> C<------> L<Elastic::Model::Results::Cached>
372            
373             =item *
374            
375             C<scrolled_results> C<----> L<Elastic::Model::Results::Scrolled>
376            
377             =item *
378            
379             C<result> C<--------------> L<Elastic::Model::Result>
380            
381             =item *
382            
383             C<bulk> C<----------------> L<Elastic::Model::Bulk>
384            
385             =back
386            
387             =head1 SEE ALSO
388            
389             =over
390            
391             =item *
392            
393             L<Elastic::Model::Role::Model>
394            
395             =item *
396            
397             L<Elastic::Manual>
398            
399             =item *
400            
401             L<Elastic::Doc>
402            
403             =back
404            
405             =head1 AUTHOR
406            
407             Clinton Gormley <drtech@cpan.org>
408            
409             =head1 COPYRIGHT AND LICENSE
410            
411             This software is copyright (c) 2015 by Clinton Gormley.
412            
413             This is free software; you can redistribute it and/or modify it under
414             the same terms as the Perl 5 programming language system itself.
415            
416             =cut
417