File Coverage

blib/lib/ElasticSearchX/Model/Document/Trait/Attribute.pm
Criterion Covered Total %
statement 18 22 81.8
branch 2 4 50.0
condition 3 3 100.0
subroutine 7 8 87.5
pod 1 3 33.3
total 31 40 77.5


line stmt bran cond sub pod time code
1             #
2             # This file is part of ElasticSearchX-Model
3             #
4             # This software is Copyright (c) 2019 by Moritz Onken.
5             #
6             # This is free software, licensed under:
7             #
8             # The (three-clause) BSD License
9             #
10             package ElasticSearchX::Model::Document::Trait::Attribute;
11             $ElasticSearchX::Model::Document::Trait::Attribute::VERSION = '2.0.1';
12             # ABSTRACT: Trait that extends the meta class of a document class
13 7     7   52 use Moose::Role;
  7         16  
  7         46  
14 7     7   38310 use ElasticSearchX::Model::Document::Mapping;
  7         20  
  7         303  
15              
16             with 'MooseX::Attribute::LazyInflator::Meta::Role::Attribute';
17              
18 7     7   2799 use ElasticSearchX::Model::Document::Types qw(:all);
  7         30  
  7         55  
19 7     7   7272 use MooseX::Types::Moose qw(ArrayRef);
  7         17  
  7         79  
20              
21             has index => ( is => 'ro' );
22             has boost => ( is => 'ro', isa => 'Num' );
23             has store => ( is => 'ro', isa => 'Str', default => 'yes' );
24             has type => ( is => 'ro', isa => 'Str', default => 'string' );
25             has parent => ( is => 'ro', isa => 'Bool', default => 0 );
26             has dynamic => ( is => 'ro', isa => 'Bool', default => 0 );
27             has analyzer =>
28             ( is => 'ro', isa => ArrayRef, coerce => 1, default => sub { [] } );
29             has not_analyzed => ( is => 'ro', isa => 'Bool', default => 1 );
30             has term_vector => ( is => 'ro', isa => 'Str' );
31             has include_in_all => ( is => 'ro', isa => 'Bool', default => 1 );
32             has source_only => ( is => 'ro', isa => 'Bool', default => 0 );
33             has include_in_root => ( is => 'ro', isa => 'Bool' );
34             has include_in_parent => ( is => 'ro', isa => 'Bool' );
35             has property => ( is => 'ro', isa => 'Bool', default => 1 );
36             has query_property => ( is => 'ro', isa => 'Bool', default => 0 );
37             has field_name =>
38             ( is => 'ro', isa => 'Str', lazy => 1, default => sub { shift->name } );
39             has isa_arrayref => (
40             is => 'ro',
41             lazy => 1,
42             isa => 'Bool',
43             builder => '_build_isa_arrayref'
44             );
45              
46             sub _build_isa_arrayref {
47 0     0   0 my $self = shift;
48 0         0 my $tc = $self->type_constraint;
49 0 0       0 return 0 unless $tc;
50 0         0 return $tc->is_a_type_of("ArrayRef");
51             }
52              
53             sub build_property {
54 15     15 1 1842 my $self = shift;
55             return {
56 15         686 ElasticSearchX::Model::Document::Mapping::maptc(
57             $self, $self->type_constraint
58             )
59             };
60             }
61              
62             before _process_options => sub {
63             my ( $self, $name, $options ) = @_;
64             %$options = ( builder => 'build_id', lazy => 1, %$options )
65             if ( $options->{id} && ref $options->{id} eq 'ARRAY' );
66              
67             $options->{traits} ||= [];
68             push(
69             @{ $options->{traits} },
70             'MooseX::Attribute::LazyInflator::Meta::Role::Attribute'
71             ) if ( $options->{property} || !exists $options->{property} );
72             };
73              
74             after _process_options => sub {
75             my ( $class, $name, $options ) = @_;
76             if ( $options->{required}
77             && !$options->{builder}
78             && !defined $options->{default} )
79             {
80             $options->{lazy} = 1;
81             $options->{required} = 1;
82             $options->{default} = sub {
83             confess "Attribute $name is required";
84             };
85             }
86             };
87              
88             sub mapping {
89 25     25 0 50 my $self = shift;
90 25 100 100     1000 return ( $self->name => $self->build_property )
91             unless ( $self->source_only || $self->parent );
92 12         35 return ();
93             }
94              
95 25     25 0 325 sub type_mapping { () }
96              
97             after install_accessors => sub {
98             my $self = shift;
99             return
100             unless (
101             $self->associated_class->does_role(
102             'ElasticSearchX::Model::Document::Role')
103             );
104             $self->associated_class->_add_field_alias(
105             $self->name => $self->field_name );
106             $self->associated_class->_add_reverse_field_alias(
107             $self->field_name => $self->name );
108             };
109              
110             1;
111              
112             __END__
113              
114             =pod
115              
116             =encoding UTF-8
117              
118             =head1 NAME
119              
120             ElasticSearchX::Model::Document::Trait::Attribute - Trait that extends the meta class of a document class
121              
122             =head1 VERSION
123              
124             version 2.0.1
125              
126             =head1 ATTRIBUTES
127              
128             =head2 property
129              
130             This defaults to C<1> and marks the attribute as ElasticSearch
131             property and thus will be added to the mapping. If you set this
132             to C<0> the attribute will act as a traditional Moose attribute.
133              
134             =head2 id
135              
136             Usually there is one property which also acts as id for the whole
137             document. If there is no attribute with the C<id> option defined
138             ElasticSearch will assign a random id. This option can either
139             be set to a true value or an arrayref. The former will make the
140             value of the attribute the id. The latter will generate a SHA1
141             digest of the concatenated values of the attributes listed in
142             the arrayref.
143              
144             Only one attribute with the C<id> option set can be present in
145             a document.
146              
147             =head2 type
148              
149             Most of the time L<ElasticSearchX::Model::Document::Mapping> will take
150             care of this option and set the correct value based on the
151             type constriant. In case it doesn't know what to do, this
152             value will be used as the type for the attribute. Defaults
153             to C<string>.
154              
155             =head2 parent
156              
157             The value of this property will be used as C<parent> id.
158             Since the parent id is stored in the C<_parent> field, it
159             is adviced to set L</source_only> to C<1> to prevent the
160             field from being stored redundantly.
161              
162             =head2 source_only
163              
164             A C<source_only> attribute is not added to the type mapping,
165             but its value is included in the C<_source> of a document.
166             This is helpful if you don't want to index the value of this
167             attribute in Elasticsearch, but still want to be able to access
168             its value.
169              
170             =head2 timestamp
171              
172             has timestamp => ( timestamp => 1, is => 'ro' );
173             has timestamp => ( timestamp => { store => 1 }, is => 'ro' );
174              
175             The attribute using this option will become the timestamp field
176             (L<http://www.elasticsearch.org/guide/reference/mapping/timestamp-field.html>).
177              
178             =head2 ttl
179              
180             has expire => ( ttl => 1, is => 'ro' );
181              
182             $document->expire(86400) # document will expire in one day
183              
184             Documents with a ttl field will set the _ttl property on the document in
185             ElasticSearch. This will cause ElasticSearch to remove the document
186             from the index automatically once the time to live has expired.
187              
188             See L<http://www.elasticsearch.org/guide/reference/mapping/ttl-field.html>.
189              
190             =head1 PASS THROUGH ATTRIBUTES
191              
192             The following attributes are passed through - as is - to the
193             type mapping.
194              
195             =head2 store
196              
197             Defaults to C<yes>.
198              
199             =head2 boost
200              
201             =head2 index
202              
203             =head2 dynamic
204              
205             By default, properties are not dynamic. That means that fields that
206             are unknown to the ElasticSearch mapping will not be indexed and
207             no dynamic mapping will be auto generated. Since the mapping is
208             generated by this module, there is no need to have the dynamic
209             mapping enabled. If you want to enable it anyway, set this attribute
210             to C<1> value.
211              
212             This will change the behaviour of C<HashRef> attributes.
213             Instead of deflating to a JSON string they will be stored as object
214             in ElasticSearch.
215              
216             =head2 analyzer
217              
218             If this attribute or L</index> is set to C<analyzed>, the field is stored
219             both analyzed and not analyzed. The not analyzed field can be accessed in
220             queries by the field name. The analyzed field will have a C<.analyzed>
221             postfix if there is only one analyzer. If there are more than one analyzer,
222             the C<.analyzed> postfix refers to the first analyzer. For all other
223             analyzers, its name is prefixed. This is done by using the C<multi_field>
224             feature of ElasticSearch.
225              
226             =head2 include_in_all
227              
228             =head2 include_in_parent
229              
230             =head2 include_in_root
231              
232             =head2 term_vector
233              
234             =head2 not_analyzed
235              
236             By default, a field is not analyzed. That means the raw value is stored
237             in the field. To add analyzed fields, either set L</index> to C<analyzed>
238             or add an L</analyzer>. Set this to C<0> if you don't want to store
239             the not analyzed version of this field along with the analyzed.
240              
241             =head1 METHODS
242              
243             =head2 build_id
244              
245             =head2 build_property
246              
247             This method is called by L<ElasticSearchX::Model::Document::Trait::Class/mapping>
248             and returns the mapping for this property as a HashRef.
249              
250             =head1 AUTHOR
251              
252             Moritz Onken
253              
254             =head1 COPYRIGHT AND LICENSE
255              
256             This software is Copyright (c) 2019 by Moritz Onken.
257              
258             This is free software, licensed under:
259              
260             The (three-clause) BSD License
261              
262             =cut