| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | package Elastic::Model::View; | 
| 2 |  |  |  |  |  |  | $Elastic::Model::View::VERSION = '0.52'; | 
| 3 | 1 |  |  | 1 |  | 1181 | use Moose; | 
|  | 1 |  |  |  |  | 3 |  | 
|  | 1 |  |  |  |  | 9 |  | 
| 4 |  |  |  |  |  |  |  | 
| 5 | 1 |  |  | 1 |  | 6693 | use Carp; | 
|  | 1 |  |  |  |  | 3 |  | 
|  | 1 |  |  |  |  | 79 |  | 
| 6 | 1 |  |  |  |  | 12 | use Elastic::Model::Types qw( | 
| 7 |  |  |  |  |  |  | IndexNames ArrayRefOfStr SortArgs | 
| 8 | 1 |  |  | 1 |  | 5 | HighlightArgs Consistency Replication); | 
|  | 1 |  |  |  |  | 3 |  | 
| 9 | 1 |  |  | 1 |  | 7716 | use MooseX::Types::Moose qw(Str Int HashRef ArrayRef Bool Num Object); | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 10 |  | 
| 10 | 1 |  |  | 1 |  | 6866 | use Elastic::Model::SearchBuilder(); | 
|  | 1 |  |  |  |  | 4 |  | 
|  | 1 |  |  |  |  | 26 |  | 
| 11 | 1 |  |  | 1 |  | 6 | use namespace::autoclean; | 
|  | 1 |  |  |  |  | 2 |  | 
|  | 1 |  |  |  |  | 17 |  | 
| 12 |  |  |  |  |  |  |  | 
| 13 |  |  |  |  |  |  |  | 
| 14 |  |  |  |  |  |  | has 'domain' => ( | 
| 15 |  |  |  |  |  |  |  | 
| 16 |  |  |  |  |  |  | isa     => IndexNames, | 
| 17 |  |  |  |  |  |  | is      => 'rw', | 
| 18 |  |  |  |  |  |  | lazy    => 1, | 
| 19 |  |  |  |  |  |  | builder => '_build_domains', | 
| 20 |  |  |  |  |  |  | coerce  => 1, | 
| 21 |  |  |  |  |  |  | ); | 
| 22 |  |  |  |  |  |  |  | 
| 23 |  |  |  |  |  |  |  | 
| 24 |  |  |  |  |  |  | has 'type' => ( | 
| 25 |  |  |  |  |  |  |  | 
| 26 |  |  |  |  |  |  | is      => 'rw', | 
| 27 |  |  |  |  |  |  | isa     => ArrayRefOfStr, | 
| 28 |  |  |  |  |  |  | default => sub { [] }, | 
| 29 |  |  |  |  |  |  | coerce  => 1, | 
| 30 |  |  |  |  |  |  | ); | 
| 31 |  |  |  |  |  |  |  | 
| 32 |  |  |  |  |  |  |  | 
| 33 |  |  |  |  |  |  | has 'query' => ( | 
| 34 |  |  |  |  |  |  |  | 
| 35 |  |  |  |  |  |  | isa => HashRef, | 
| 36 |  |  |  |  |  |  | is  => 'rw', | 
| 37 |  |  |  |  |  |  | ); | 
| 38 |  |  |  |  |  |  |  | 
| 39 |  |  |  |  |  |  |  | 
| 40 |  |  |  |  |  |  | has 'filter' => ( | 
| 41 |  |  |  |  |  |  |  | 
| 42 |  |  |  |  |  |  | isa => HashRef, | 
| 43 |  |  |  |  |  |  | is  => 'rw', | 
| 44 |  |  |  |  |  |  | ); | 
| 45 |  |  |  |  |  |  |  | 
| 46 |  |  |  |  |  |  |  | 
| 47 |  |  |  |  |  |  | has 'post_filter' => ( | 
| 48 |  |  |  |  |  |  |  | 
| 49 |  |  |  |  |  |  | isa => HashRef, | 
| 50 |  |  |  |  |  |  | is  => 'rw', | 
| 51 |  |  |  |  |  |  | ); | 
| 52 |  |  |  |  |  |  |  | 
| 53 |  |  |  |  |  |  |  | 
| 54 |  |  |  |  |  |  | has 'aggs' => ( | 
| 55 |  |  |  |  |  |  |  | 
| 56 |  |  |  |  |  |  | traits  => ['Hash'], | 
| 57 |  |  |  |  |  |  | isa     => HashRef [HashRef], | 
| 58 |  |  |  |  |  |  | is      => 'rw', | 
| 59 |  |  |  |  |  |  | handles => { | 
| 60 |  |  |  |  |  |  | add_agg    => 'set', | 
| 61 |  |  |  |  |  |  | remove_agg => 'delete', | 
| 62 |  |  |  |  |  |  | get_agg    => 'get' | 
| 63 |  |  |  |  |  |  | } | 
| 64 |  |  |  |  |  |  | ); | 
| 65 |  |  |  |  |  |  |  | 
| 66 |  |  |  |  |  |  |  | 
| 67 |  |  |  |  |  |  | has 'facets' => ( | 
| 68 |  |  |  |  |  |  |  | 
| 69 |  |  |  |  |  |  | traits  => ['Hash'], | 
| 70 |  |  |  |  |  |  | isa     => HashRef [HashRef], | 
| 71 |  |  |  |  |  |  | is      => 'rw', | 
| 72 |  |  |  |  |  |  | handles => { | 
| 73 |  |  |  |  |  |  | add_facet    => 'set', | 
| 74 |  |  |  |  |  |  | remove_facet => 'delete', | 
| 75 |  |  |  |  |  |  | get_facet    => 'get' | 
| 76 |  |  |  |  |  |  | } | 
| 77 |  |  |  |  |  |  | ); | 
| 78 |  |  |  |  |  |  |  | 
| 79 |  |  |  |  |  |  |  | 
| 80 |  |  |  |  |  |  | has 'fields' => ( | 
| 81 |  |  |  |  |  |  |  | 
| 82 |  |  |  |  |  |  | isa     => ArrayRefOfStr, | 
| 83 |  |  |  |  |  |  | coerce  => 1, | 
| 84 |  |  |  |  |  |  | is      => 'rw', | 
| 85 |  |  |  |  |  |  | default => sub { [] }, | 
| 86 |  |  |  |  |  |  | ); | 
| 87 |  |  |  |  |  |  |  | 
| 88 |  |  |  |  |  |  |  | 
| 89 |  |  |  |  |  |  | has 'from' => ( | 
| 90 |  |  |  |  |  |  |  | 
| 91 |  |  |  |  |  |  | isa     => Int, | 
| 92 |  |  |  |  |  |  | is      => 'rw', | 
| 93 |  |  |  |  |  |  | default => 0, | 
| 94 |  |  |  |  |  |  | ); | 
| 95 |  |  |  |  |  |  |  | 
| 96 |  |  |  |  |  |  |  | 
| 97 |  |  |  |  |  |  | has 'size' => ( | 
| 98 |  |  |  |  |  |  |  | 
| 99 |  |  |  |  |  |  | isa       => Int, | 
| 100 |  |  |  |  |  |  | is        => 'rw', | 
| 101 |  |  |  |  |  |  | lazy      => 1, | 
| 102 |  |  |  |  |  |  | default   => 10, | 
| 103 |  |  |  |  |  |  | predicate => '_has_size', | 
| 104 |  |  |  |  |  |  | ); | 
| 105 |  |  |  |  |  |  |  | 
| 106 |  |  |  |  |  |  |  | 
| 107 |  |  |  |  |  |  | has 'sort' => ( | 
| 108 |  |  |  |  |  |  |  | 
| 109 |  |  |  |  |  |  | isa    => SortArgs, | 
| 110 |  |  |  |  |  |  | is     => 'rw', | 
| 111 |  |  |  |  |  |  | coerce => 1, | 
| 112 |  |  |  |  |  |  | ); | 
| 113 |  |  |  |  |  |  |  | 
| 114 |  |  |  |  |  |  |  | 
| 115 |  |  |  |  |  |  | has 'highlighting' => ( | 
| 116 |  |  |  |  |  |  |  | 
| 117 |  |  |  |  |  |  | isa     => HashRef, | 
| 118 |  |  |  |  |  |  | is      => 'rw', | 
| 119 |  |  |  |  |  |  | trigger => \&_check_no_fields, | 
| 120 |  |  |  |  |  |  | ); | 
| 121 |  |  |  |  |  |  |  | 
| 122 |  |  |  |  |  |  |  | 
| 123 |  |  |  |  |  |  | has 'highlight' => ( | 
| 124 |  |  |  |  |  |  |  | 
| 125 |  |  |  |  |  |  | is     => 'rw', | 
| 126 |  |  |  |  |  |  | isa    => HighlightArgs, | 
| 127 |  |  |  |  |  |  | coerce => 1, | 
| 128 |  |  |  |  |  |  | ); | 
| 129 |  |  |  |  |  |  |  | 
| 130 |  |  |  |  |  |  |  | 
| 131 |  |  |  |  |  |  | has 'index_boosts' => ( | 
| 132 |  |  |  |  |  |  |  | 
| 133 |  |  |  |  |  |  | isa => HashRef [Num], | 
| 134 |  |  |  |  |  |  | is => 'rw', | 
| 135 |  |  |  |  |  |  | traits  => ['Hash'], | 
| 136 |  |  |  |  |  |  | handles => { | 
| 137 |  |  |  |  |  |  | add_index_boost    => 'set', | 
| 138 |  |  |  |  |  |  | remove_index_boost => 'delete', | 
| 139 |  |  |  |  |  |  | get_index_boost    => 'get' | 
| 140 |  |  |  |  |  |  | } | 
| 141 |  |  |  |  |  |  | ); | 
| 142 |  |  |  |  |  |  |  | 
| 143 |  |  |  |  |  |  |  | 
| 144 |  |  |  |  |  |  | has 'min_score' => ( | 
| 145 |  |  |  |  |  |  |  | 
| 146 |  |  |  |  |  |  | isa => Num, | 
| 147 |  |  |  |  |  |  | is  => 'rw', | 
| 148 |  |  |  |  |  |  | ); | 
| 149 |  |  |  |  |  |  |  | 
| 150 |  |  |  |  |  |  |  | 
| 151 |  |  |  |  |  |  | has 'preference' => ( | 
| 152 |  |  |  |  |  |  |  | 
| 153 |  |  |  |  |  |  | isa => Str, | 
| 154 |  |  |  |  |  |  | is  => 'rw', | 
| 155 |  |  |  |  |  |  | ); | 
| 156 |  |  |  |  |  |  |  | 
| 157 |  |  |  |  |  |  |  | 
| 158 |  |  |  |  |  |  | has 'routing' => ( | 
| 159 |  |  |  |  |  |  |  | 
| 160 |  |  |  |  |  |  | isa    => ArrayRefOfStr, | 
| 161 |  |  |  |  |  |  | coerce => 1, | 
| 162 |  |  |  |  |  |  | is     => 'rw', | 
| 163 |  |  |  |  |  |  | ); | 
| 164 |  |  |  |  |  |  |  | 
| 165 |  |  |  |  |  |  |  | 
| 166 |  |  |  |  |  |  | has 'include_paths' => ( | 
| 167 |  |  |  |  |  |  |  | 
| 168 |  |  |  |  |  |  | is        => 'rw', | 
| 169 |  |  |  |  |  |  | isa       => ArrayRef [Str], | 
| 170 |  |  |  |  |  |  | predicate => '_has_include_paths' | 
| 171 |  |  |  |  |  |  | ); | 
| 172 |  |  |  |  |  |  |  | 
| 173 |  |  |  |  |  |  |  | 
| 174 |  |  |  |  |  |  | has 'exclude_paths' => ( | 
| 175 |  |  |  |  |  |  |  | 
| 176 |  |  |  |  |  |  | is        => 'rw', | 
| 177 |  |  |  |  |  |  | isa       => ArrayRef [Str], | 
| 178 |  |  |  |  |  |  | predicate => '_has_exclude_paths' | 
| 179 |  |  |  |  |  |  | ); | 
| 180 |  |  |  |  |  |  |  | 
| 181 |  |  |  |  |  |  |  | 
| 182 |  |  |  |  |  |  | has 'script_fields' => ( | 
| 183 |  |  |  |  |  |  |  | 
| 184 |  |  |  |  |  |  | isa     => HashRef, | 
| 185 |  |  |  |  |  |  | is      => 'rw', | 
| 186 |  |  |  |  |  |  | traits  => ['Hash'], | 
| 187 |  |  |  |  |  |  | handles => { | 
| 188 |  |  |  |  |  |  | add_script_field    => 'set', | 
| 189 |  |  |  |  |  |  | remove_script_field => 'delete', | 
| 190 |  |  |  |  |  |  | get_script_field    => 'get' | 
| 191 |  |  |  |  |  |  | } | 
| 192 |  |  |  |  |  |  | ); | 
| 193 |  |  |  |  |  |  |  | 
| 194 |  |  |  |  |  |  |  | 
| 195 |  |  |  |  |  |  | has 'timeout' => ( | 
| 196 |  |  |  |  |  |  |  | 
| 197 |  |  |  |  |  |  | isa => Str, | 
| 198 |  |  |  |  |  |  | is  => 'rw', | 
| 199 |  |  |  |  |  |  | ); | 
| 200 |  |  |  |  |  |  |  | 
| 201 |  |  |  |  |  |  |  | 
| 202 |  |  |  |  |  |  | has 'explain' => ( | 
| 203 |  |  |  |  |  |  |  | 
| 204 |  |  |  |  |  |  | is  => 'rw', | 
| 205 |  |  |  |  |  |  | isa => Bool, | 
| 206 |  |  |  |  |  |  | ); | 
| 207 |  |  |  |  |  |  |  | 
| 208 |  |  |  |  |  |  |  | 
| 209 |  |  |  |  |  |  | has 'stats' => ( | 
| 210 |  |  |  |  |  |  |  | 
| 211 |  |  |  |  |  |  | is     => 'rw', | 
| 212 |  |  |  |  |  |  | isa    => ArrayRefOfStr, | 
| 213 |  |  |  |  |  |  | coerce => 1, | 
| 214 |  |  |  |  |  |  | ); | 
| 215 |  |  |  |  |  |  |  | 
| 216 |  |  |  |  |  |  |  | 
| 217 |  |  |  |  |  |  | has 'track_scores' => ( | 
| 218 |  |  |  |  |  |  |  | 
| 219 |  |  |  |  |  |  | isa => Bool, | 
| 220 |  |  |  |  |  |  | is  => 'rw', | 
| 221 |  |  |  |  |  |  | ); | 
| 222 |  |  |  |  |  |  |  | 
| 223 |  |  |  |  |  |  |  | 
| 224 |  |  |  |  |  |  | has 'consistency' => ( | 
| 225 |  |  |  |  |  |  |  | 
| 226 |  |  |  |  |  |  | is  => 'rw', | 
| 227 |  |  |  |  |  |  | isa => Consistency, | 
| 228 |  |  |  |  |  |  | ); | 
| 229 |  |  |  |  |  |  |  | 
| 230 |  |  |  |  |  |  |  | 
| 231 |  |  |  |  |  |  | has 'replication' => ( | 
| 232 |  |  |  |  |  |  |  | 
| 233 |  |  |  |  |  |  | is  => 'rw', | 
| 234 |  |  |  |  |  |  | isa => Replication | 
| 235 |  |  |  |  |  |  | ); | 
| 236 |  |  |  |  |  |  |  | 
| 237 |  |  |  |  |  |  |  | 
| 238 |  |  |  |  |  |  | has 'search_builder' => ( | 
| 239 |  |  |  |  |  |  |  | 
| 240 |  |  |  |  |  |  | isa     => Object, | 
| 241 |  |  |  |  |  |  | is      => 'rw', | 
| 242 |  |  |  |  |  |  | lazy    => 1, | 
| 243 |  |  |  |  |  |  | builder => '_build_search_builder', | 
| 244 |  |  |  |  |  |  | ); | 
| 245 |  |  |  |  |  |  |  | 
| 246 |  |  |  |  |  |  |  | 
| 247 |  |  |  |  |  |  | has 'cache' => ( | 
| 248 |  |  |  |  |  |  |  | 
| 249 |  |  |  |  |  |  | is  => 'rw', | 
| 250 |  |  |  |  |  |  | isa => Object, | 
| 251 |  |  |  |  |  |  | ); | 
| 252 |  |  |  |  |  |  |  | 
| 253 |  |  |  |  |  |  |  | 
| 254 |  |  |  |  |  |  | has 'cache_opts' => ( | 
| 255 |  |  |  |  |  |  |  | 
| 256 |  |  |  |  |  |  | is  => 'rw', | 
| 257 |  |  |  |  |  |  | isa => HashRef, | 
| 258 |  |  |  |  |  |  | ); | 
| 259 |  |  |  |  |  |  |  | 
| 260 |  |  |  |  |  |  |  | 
| 261 | 0 |  |  | 0 |  | 0 | sub _build_search_builder { Elastic::Model::SearchBuilder->new } | 
| 262 |  |  |  |  |  |  |  | 
| 263 |  |  |  |  |  |  |  | 
| 264 |  |  |  |  |  |  |  | 
| 265 |  |  |  |  |  |  | sub queryb { | 
| 266 |  |  |  |  |  |  |  | 
| 267 | 0 |  |  | 0 | 1 | 0 | my $self  = shift; | 
| 268 | 0 | 0 |  |  |  | 0 | my @args  = @_ > 1 ? {@_} : shift(); | 
| 269 | 0 | 0 |  |  |  | 0 | my $query = $self->search_builder->query(@args) | 
| 270 |  |  |  |  |  |  | or return $self->_clone_self; | 
| 271 | 0 |  |  |  |  | 0 | $self->query( $query->{query} ); | 
| 272 |  |  |  |  |  |  | } | 
| 273 |  |  |  |  |  |  |  | 
| 274 |  |  |  |  |  |  |  | 
| 275 |  |  |  |  |  |  | sub filterb { | 
| 276 |  |  |  |  |  |  |  | 
| 277 | 0 |  |  | 0 | 1 | 0 | my $self   = shift; | 
| 278 | 0 | 0 |  |  |  | 0 | my @args   = @_ > 1 ? {@_} : shift(); | 
| 279 | 0 | 0 |  |  |  | 0 | my $filter = $self->search_builder->filter(@args) | 
| 280 |  |  |  |  |  |  | or return $self->_clone_self; | 
| 281 | 0 |  |  |  |  | 0 | $self->filter( $filter->{filter} ); | 
| 282 |  |  |  |  |  |  | } | 
| 283 |  |  |  |  |  |  |  | 
| 284 |  |  |  |  |  |  |  | 
| 285 |  |  |  |  |  |  | sub post_filterb { | 
| 286 |  |  |  |  |  |  |  | 
| 287 | 0 |  |  | 0 | 1 | 0 | my $self   = shift; | 
| 288 | 0 | 0 |  |  |  | 0 | my @args   = @_ > 1 ? {@_} : shift(); | 
| 289 | 0 | 0 |  |  |  | 0 | my $filter = $self->search_builder->filter(@args) | 
| 290 |  |  |  |  |  |  | or return $self->_clone_self; | 
| 291 | 0 |  |  |  |  | 0 | $self->post_filter( $filter->{filter} ); | 
| 292 |  |  |  |  |  |  | } | 
| 293 |  |  |  |  |  |  |  | 
| 294 |  |  |  |  |  |  |  | 
| 295 |  |  |  |  |  |  |  | 
| 296 |  |  |  |  |  |  |  | 
| 297 |  |  |  |  |  |  |  | 
| 298 |  |  |  |  |  |  | around [ | 
| 299 |  |  |  |  |  |  |  | 
| 300 |  |  |  |  |  |  | 'from',           'size',        'timeout',   'track_scores', | 
| 301 |  |  |  |  |  |  | 'search_builder', 'preference',  'min_score', 'explain', | 
| 302 |  |  |  |  |  |  | 'consistency',    'replication', 'cache' | 
| 303 |  |  |  |  |  |  |  | 
| 304 |  |  |  |  |  |  | ] => sub { _clone_args( \&_scalar_args, @_ ) }; | 
| 305 |  |  |  |  |  |  |  | 
| 306 |  |  |  |  |  |  | around [ | 
| 307 |  |  |  |  |  |  |  | 
| 308 |  |  |  |  |  |  | 'domain',        'type', 'fields', 'sort', 'routing', 'stats', | 
| 309 |  |  |  |  |  |  | 'include_paths', 'exclude_paths' | 
| 310 |  |  |  |  |  |  |  | 
| 311 |  |  |  |  |  |  | ] => sub { _clone_args( \&_array_args, @_ ) }; | 
| 312 |  |  |  |  |  |  |  | 
| 313 |  |  |  |  |  |  | around [ | 
| 314 |  |  |  |  |  |  |  | 
| 315 |  |  |  |  |  |  | 'aggs',  'facets', 'index_boosts', 'script_fields', 'highlighting', | 
| 316 |  |  |  |  |  |  | 'query', 'filter', 'post_filter',  'cache_opts' | 
| 317 |  |  |  |  |  |  |  | 
| 318 |  |  |  |  |  |  | ] => sub { _clone_args( \&_hash_args, @_ ) }; | 
| 319 |  |  |  |  |  |  |  | 
| 320 |  |  |  |  |  |  |  | 
| 321 |  |  |  |  |  |  | around 'highlight' | 
| 322 |  |  |  |  |  |  |  | 
| 323 |  |  |  |  |  |  | => sub { _clone_args( \&_highlight_args, @_ ) }; | 
| 324 |  |  |  |  |  |  |  | 
| 325 |  |  |  |  |  |  | for my $name ( 'agg', 'facet', 'index_boost', 'script_field' ) { | 
| 326 |  |  |  |  |  |  | my $attr = $name . 's'; | 
| 327 |  |  |  |  |  |  | for my $method ( "add_$name", "remove_$name" ) { | 
| 328 |  |  |  |  |  |  | around $method => sub { | 
| 329 |  |  |  |  |  |  | my $orig = shift; | 
| 330 |  |  |  |  |  |  | my $self = shift; | 
| 331 |  |  |  |  |  |  | my %hash = %{ $self->$attr || {} }; | 
| 332 |  |  |  |  |  |  | $self = $self->$attr( \%hash ); | 
| 333 |  |  |  |  |  |  | $self->$orig(@_); | 
| 334 |  |  |  |  |  |  | return $self; | 
| 335 |  |  |  |  |  |  | }; | 
| 336 |  |  |  |  |  |  | } | 
| 337 |  |  |  |  |  |  | } | 
| 338 |  |  |  |  |  |  |  | 
| 339 |  |  |  |  |  |  |  | 
| 340 | 0 |  |  | 0 |  | 0 | sub _scalar_args    {@_} | 
| 341 | 0 | 0 |  | 0 |  | 0 | sub _hash_args      { @_ > 1 ? {@_} : @_ } | 
| 342 | 0 | 0 |  | 0 |  | 0 | sub _highlight_args { ref $_[0] ? shift : \@_ } | 
| 343 | 0 | 0 |  | 0 |  | 0 | sub _array_args     { ref $_[0] eq 'ARRAY' ? shift() : \@_ } | 
| 344 |  |  |  |  |  |  |  | 
| 345 |  |  |  |  |  |  |  | 
| 346 |  |  |  |  |  |  |  | 
| 347 |  |  |  |  |  |  | sub _clone_args { | 
| 348 |  |  |  |  |  |  |  | 
| 349 | 0 |  |  | 0 |  | 0 | my $args = shift; | 
| 350 | 0 |  |  |  |  | 0 | my $orig = shift; | 
| 351 | 0 |  |  |  |  | 0 | my $self = shift; | 
| 352 | 0 | 0 |  |  |  | 0 | if (@_) { | 
| 353 | 0 |  |  |  |  | 0 | $self = bless {%$self}, ref $self; | 
| 354 | 0 |  |  |  |  | 0 | $self->$orig( $args->(@_) ); | 
| 355 | 0 |  |  |  |  | 0 | return $self; | 
| 356 |  |  |  |  |  |  | } | 
| 357 | 0 |  |  |  |  | 0 | $self->$orig(); | 
| 358 |  |  |  |  |  |  | } | 
| 359 |  |  |  |  |  |  |  | 
| 360 |  |  |  |  |  |  |  | 
| 361 |  |  |  |  |  |  | sub _clone_self { | 
| 362 |  |  |  |  |  |  |  | 
| 363 | 0 |  |  | 0 |  | 0 | my $self = shift; | 
| 364 | 0 |  |  |  |  | 0 | return bless {%$self}, ref $self; | 
| 365 |  |  |  |  |  |  | } | 
| 366 |  |  |  |  |  |  |  | 
| 367 |  |  |  |  |  |  |  | 
| 368 |  |  |  |  |  |  | sub _check_no_fields { | 
| 369 |  |  |  |  |  |  |  | 
| 370 | 0 |  |  | 0 |  | 0 | my ( $self, $val ) = @_; | 
| 371 |  |  |  |  |  |  | croak "Use the (highlight) attribute to set the fields to highlight" | 
| 372 | 0 | 0 |  |  |  | 0 | if $val->{fields}; | 
| 373 |  |  |  |  |  |  | } | 
| 374 |  |  |  |  |  |  |  | 
| 375 | 1 |  |  | 1 |  | 1473 | no Moose; | 
|  | 1 |  |  |  |  | 3 |  | 
|  | 1 |  |  |  |  | 11 |  | 
| 376 |  |  |  |  |  |  |  | 
| 377 |  |  |  |  |  |  |  | 
| 378 |  |  |  |  |  |  | sub BUILD { | 
| 379 |  |  |  |  |  |  |  | 
| 380 | 1 |  |  | 1 | 0 | 2 | my ( $orig_self, $args ) = @_; | 
| 381 | 1 |  |  |  |  | 2 | my $self = $orig_self; | 
| 382 | 1 |  |  |  |  | 3 | for (qw(queryb filterb post_filterb)) { | 
| 383 |  |  |  |  |  |  | $self = $self->$_( $args->{$_} ) | 
| 384 | 3 | 50 |  |  |  | 10 | if defined $args->{$_}; | 
| 385 |  |  |  |  |  |  | } | 
| 386 |  |  |  |  |  |  |  | 
| 387 | 1 |  |  |  |  | 2 | %{$orig_self} = %{$self}; | 
|  | 1 |  |  |  |  | 43 |  | 
|  | 1 |  |  |  |  | 4 |  | 
| 388 |  |  |  |  |  |  | } | 
| 389 |  |  |  |  |  |  |  | 
| 390 |  |  |  |  |  |  |  | 
| 391 |  |  |  |  |  |  | sub _build_domains { | 
| 392 |  |  |  |  |  |  |  | 
| 393 | 0 |  |  | 0 |  |  | my $self       = shift; | 
| 394 | 0 |  |  |  |  |  | my $namespaces = $self->model->namespaces; | 
| 395 | 0 |  |  |  |  |  | [   map { $_, @{ $namespaces->{$_}->fixed_domains } } | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
| 396 |  |  |  |  |  |  | sort keys %$namespaces | 
| 397 |  |  |  |  |  |  | ]; | 
| 398 |  |  |  |  |  |  | } | 
| 399 |  |  |  |  |  |  |  | 
| 400 |  |  |  |  |  |  |  | 
| 401 |  |  |  |  |  |  | sub search { | 
| 402 |  |  |  |  |  |  |  | 
| 403 | 0 |  |  | 0 | 1 |  | my $self = shift; | 
| 404 | 0 |  |  |  |  |  | $self->model->results_class->new( search => $self->_build_search ) | 
| 405 |  |  |  |  |  |  | ->as_results; | 
| 406 |  |  |  |  |  |  | } | 
| 407 |  |  |  |  |  |  |  | 
| 408 |  |  |  |  |  |  |  | 
| 409 |  |  |  |  |  |  | sub cached_search { | 
| 410 |  |  |  |  |  |  |  | 
| 411 | 0 |  |  | 0 | 1 |  | my $self  = shift; | 
| 412 | 0 | 0 |  |  |  |  | my $cache = $self->cache | 
| 413 |  |  |  |  |  |  | or return $self->search; | 
| 414 |  |  |  |  |  |  |  | 
| 415 |  |  |  |  |  |  | my %cache_opts | 
| 416 | 0 | 0 |  |  |  |  | = ( %{ $self->cache_opts || {} }, @_ == 1 ? %{ $_[0] } : @_ ); | 
|  | 0 | 0 |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
| 417 |  |  |  |  |  |  |  | 
| 418 | 0 |  |  |  |  |  | $self->model->cached_results_class->new( | 
| 419 |  |  |  |  |  |  | search     => $self->_build_search, | 
| 420 |  |  |  |  |  |  | cache      => $cache, | 
| 421 |  |  |  |  |  |  | cache_opts => \%cache_opts | 
| 422 |  |  |  |  |  |  | )->as_results; | 
| 423 |  |  |  |  |  |  | } | 
| 424 |  |  |  |  |  |  |  | 
| 425 |  |  |  |  |  |  |  | 
| 426 | 0 |  |  | 0 | 1 |  | sub scroll { shift->_scroll(@_)->as_results } | 
| 427 |  |  |  |  |  |  |  | 
| 428 |  |  |  |  |  |  |  | 
| 429 |  |  |  |  |  |  |  | 
| 430 |  |  |  |  |  |  | sub scan { | 
| 431 |  |  |  |  |  |  |  | 
| 432 | 0 |  |  | 0 | 1 |  | my $self = shift; | 
| 433 |  |  |  |  |  |  | croak "A scan cannot be combined with sorting" | 
| 434 | 0 | 0 |  |  |  |  | if @{ $self->sort || [] }; | 
|  | 0 | 0 |  |  |  |  |  | 
| 435 | 0 |  |  |  |  |  | return $self->_scroll( shift, search_type => 'scan', @_ )->as_objects; | 
| 436 |  |  |  |  |  |  | } | 
| 437 |  |  |  |  |  |  |  | 
| 438 |  |  |  |  |  |  |  | 
| 439 |  |  |  |  |  |  | sub _scroll { | 
| 440 |  |  |  |  |  |  |  | 
| 441 | 0 |  |  | 0 |  |  | my $self = shift; | 
| 442 | 0 |  | 0 |  |  |  | my $search = $self->_build_search( scroll => shift() || '1m', @_ ); | 
| 443 | 0 |  |  |  |  |  | return $self->model->scrolled_results_class->new( search => $search ); | 
| 444 |  |  |  |  |  |  | } | 
| 445 |  |  |  |  |  |  |  | 
| 446 |  |  |  |  |  |  |  | 
| 447 |  |  |  |  |  |  | sub delete { | 
| 448 |  |  |  |  |  |  |  | 
| 449 | 0 |  |  | 0 | 1 |  | my $self = shift; | 
| 450 | 0 |  |  |  |  |  | $self->model->store->delete_by_query( $self->_build_delete(@_) ); | 
| 451 |  |  |  |  |  |  | } | 
| 452 |  |  |  |  |  |  |  | 
| 453 |  |  |  |  |  |  |  | 
| 454 | 0 |  |  | 0 | 1 |  | sub first { shift->size(1)->search(@_)->first } | 
| 455 | 0 |  |  | 0 | 1 |  | sub total { shift->size(0)->search(@_)->total } | 
| 456 |  |  |  |  |  |  |  | 
| 457 |  |  |  |  |  |  |  | 
| 458 |  |  |  |  |  |  |  | 
| 459 |  |  |  |  |  |  | sub _build_search { | 
| 460 |  |  |  |  |  |  |  | 
| 461 | 0 |  |  | 0 |  |  | my $self = shift; | 
| 462 |  |  |  |  |  |  |  | 
| 463 | 0 |  |  |  |  |  | my ( $highlight, $hfields ); | 
| 464 | 0 | 0 | 0 |  |  |  | if ( $hfields = $self->highlight and keys %$hfields ) { | 
| 465 | 0 | 0 |  |  |  |  | $highlight = { %{ $self->highlighting || {} }, fields => $hfields }; | 
|  | 0 |  |  |  |  |  |  | 
| 466 |  |  |  |  |  |  | } | 
| 467 |  |  |  |  |  |  |  | 
| 468 | 0 |  |  |  |  |  | my $fields = $self->fields; | 
| 469 |  |  |  |  |  |  |  | 
| 470 | 0 |  |  |  |  |  | my $source; | 
| 471 | 0 | 0 |  |  |  |  | $source->{include} = $self->include_paths | 
| 472 |  |  |  |  |  |  | if $self->_has_include_paths; | 
| 473 | 0 | 0 |  |  |  |  | $source->{exclude} = $self->exclude_paths | 
| 474 |  |  |  |  |  |  | if $self->_has_exclude_paths; | 
| 475 |  |  |  |  |  |  |  | 
| 476 | 0 | 0 | 0 |  |  |  | $fields = ['_source'] unless $source || @$fields; | 
| 477 |  |  |  |  |  |  |  | 
| 478 |  |  |  |  |  |  | my %args = _strip_undef( | 
| 479 | 0 |  |  |  |  |  | (   map { $_ => $self->$_ } | 
|  | 0 |  |  |  |  |  |  | 
| 480 |  |  |  |  |  |  | qw( | 
| 481 |  |  |  |  |  |  | type sort from size aggs | 
| 482 |  |  |  |  |  |  | min_score post_filter preference routing stats | 
| 483 |  |  |  |  |  |  | script_fields timeout track_scores explain | 
| 484 |  |  |  |  |  |  | ) | 
| 485 |  |  |  |  |  |  | ), | 
| 486 |  |  |  |  |  |  | facets        => $self->_build_facets, | 
| 487 |  |  |  |  |  |  | index         => $self->domain, | 
| 488 |  |  |  |  |  |  | query         => $self->_build_query, | 
| 489 |  |  |  |  |  |  | highlight     => $highlight, | 
| 490 |  |  |  |  |  |  | indices_boost => $self->index_boosts, | 
| 491 |  |  |  |  |  |  | @_, | 
| 492 |  |  |  |  |  |  | version => 1, | 
| 493 |  |  |  |  |  |  | fields  => [ '_parent', '_routing', @$fields ] | 
| 494 |  |  |  |  |  |  | ); | 
| 495 | 0 | 0 |  |  |  |  | $args{_source} = $source | 
| 496 |  |  |  |  |  |  | if defined $source; | 
| 497 | 0 |  |  |  |  |  | return \%args; | 
| 498 |  |  |  |  |  |  | } | 
| 499 |  |  |  |  |  |  |  | 
| 500 |  |  |  |  |  |  |  | 
| 501 |  |  |  |  |  |  | sub _build_facets { | 
| 502 |  |  |  |  |  |  |  | 
| 503 | 0 |  |  | 0 |  |  | my $self = shift; | 
| 504 | 0 | 0 |  |  |  |  | return undef unless $self->facets; | 
| 505 |  |  |  |  |  |  |  | 
| 506 | 0 |  |  |  |  |  | my $facets = { %{ $self->facets } }; | 
|  | 0 |  |  |  |  |  |  | 
| 507 |  |  |  |  |  |  |  | 
| 508 | 0 |  |  |  |  |  | for ( values %$facets ) { | 
| 509 | 0 | 0 |  |  |  |  | die "All (facets) must be HASH refs" unless ref $_ eq 'HASH'; | 
| 510 | 0 |  |  |  |  |  | $_ = my $facet = {%$_}; | 
| 511 | 0 |  |  |  |  |  | $self->_to_dsl( | 
| 512 |  |  |  |  |  |  | {   queryb        => 'query', | 
| 513 |  |  |  |  |  |  | filterb       => 'filter', | 
| 514 |  |  |  |  |  |  | facet_filterb => 'facet_filter' | 
| 515 |  |  |  |  |  |  | }, | 
| 516 |  |  |  |  |  |  | $facet | 
| 517 |  |  |  |  |  |  | ); | 
| 518 |  |  |  |  |  |  | } | 
| 519 |  |  |  |  |  |  |  | 
| 520 | 0 |  |  |  |  |  | $facets; | 
| 521 |  |  |  |  |  |  | } | 
| 522 |  |  |  |  |  |  |  | 
| 523 |  |  |  |  |  |  |  | 
| 524 |  |  |  |  |  |  | sub _to_dsl { | 
| 525 |  |  |  |  |  |  |  | 
| 526 | 0 |  |  | 0 |  |  | my ( $self, $ops ) = ( shift, shift ); | 
| 527 |  |  |  |  |  |  |  | 
| 528 | 0 |  |  |  |  |  | my $builder; | 
| 529 | 0 |  |  |  |  |  | for my $clause (@_) { | 
| 530 | 0 |  |  |  |  |  | while ( my ( $old, $new ) = each %$ops ) { | 
| 531 | 0 | 0 |  |  |  |  | my $src = delete $clause->{$old} or next; | 
| 532 | 0 | 0 |  |  |  |  | die "Cannot specify $old and $new parameters.\n" if $clause->{$new}; | 
| 533 |  |  |  |  |  |  |  | 
| 534 | 0 |  | 0 |  |  |  | $builder ||= $self->search_builder; | 
| 535 | 0 | 0 |  |  |  |  | my $method = $new eq 'query' ? 'query' : 'filter'; | 
| 536 | 0 | 0 |  |  |  |  | my $sub_clause = $builder->$method($src) or next; | 
| 537 | 0 |  |  |  |  |  | $clause->{$new} = $sub_clause->{$method}; | 
| 538 |  |  |  |  |  |  | } | 
| 539 |  |  |  |  |  |  | } | 
| 540 |  |  |  |  |  |  | } | 
| 541 |  |  |  |  |  |  |  | 
| 542 |  |  |  |  |  |  |  | 
| 543 |  |  |  |  |  |  | sub _build_query { | 
| 544 |  |  |  |  |  |  |  | 
| 545 | 0 |  |  | 0 |  |  | my $self = shift; | 
| 546 | 0 |  |  |  |  |  | my $q    = $self->query; | 
| 547 | 0 |  |  |  |  |  | my $f    = $self->filter; | 
| 548 | 0 | 0 | 0 |  |  |  | return { match_all => {} } unless $q || $f; | 
| 549 |  |  |  |  |  |  |  | 
| 550 |  |  |  |  |  |  | return | 
| 551 | 0 | 0 |  |  |  |  | !$q ? { constant_score => { filter => $f } } | 
|  |  | 0 |  |  |  |  |  | 
| 552 |  |  |  |  |  |  | : $f ? { filtered => { query => $q, filter => $f } } | 
| 553 |  |  |  |  |  |  | :      $q; | 
| 554 |  |  |  |  |  |  | } | 
| 555 |  |  |  |  |  |  |  | 
| 556 |  |  |  |  |  |  |  | 
| 557 |  |  |  |  |  |  | sub _build_delete { | 
| 558 |  |  |  |  |  |  |  | 
| 559 | 0 |  |  | 0 |  |  | my $self = shift; | 
| 560 |  |  |  |  |  |  | my %args = _strip_undef( | 
| 561 |  |  |  |  |  |  | index => $self->domain, | 
| 562 | 0 |  |  |  |  |  | ( map { $_ => $self->$_ } qw(type routing consistency replication) ), | 
|  | 0 |  |  |  |  |  |  | 
| 563 |  |  |  |  |  |  | @_, | 
| 564 |  |  |  |  |  |  | query => $self->_build_query, | 
| 565 |  |  |  |  |  |  | ); | 
| 566 | 0 |  |  |  |  |  | return \%args; | 
| 567 |  |  |  |  |  |  | } | 
| 568 |  |  |  |  |  |  |  | 
| 569 |  |  |  |  |  |  |  | 
| 570 |  |  |  |  |  |  | sub _strip_undef { | 
| 571 |  |  |  |  |  |  |  | 
| 572 | 0 |  |  | 0 |  |  | my %args = @_; | 
| 573 | 0 |  |  |  |  |  | return map { $_ => $args{$_} } grep { defined $args{$_} } keys %args; | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
| 574 |  |  |  |  |  |  | } | 
| 575 |  |  |  |  |  |  | 1; | 
| 576 |  |  |  |  |  |  |  | 
| 577 |  |  |  |  |  |  | =pod | 
| 578 |  |  |  |  |  |  |  | 
| 579 |  |  |  |  |  |  | =encoding UTF-8 | 
| 580 |  |  |  |  |  |  |  | 
| 581 |  |  |  |  |  |  | =head1 NAME | 
| 582 |  |  |  |  |  |  |  | 
| 583 |  |  |  |  |  |  | Elastic::Model::View - Views to query your docs in Elasticsearch | 
| 584 |  |  |  |  |  |  |  | 
| 585 |  |  |  |  |  |  | =head1 VERSION | 
| 586 |  |  |  |  |  |  |  | 
| 587 |  |  |  |  |  |  | version 0.52 | 
| 588 |  |  |  |  |  |  |  | 
| 589 |  |  |  |  |  |  | =head1 SYNOPSIS | 
| 590 |  |  |  |  |  |  |  | 
| 591 |  |  |  |  |  |  | $view    = $model->view();         # all domains and types known to the model | 
| 592 |  |  |  |  |  |  | $view    = $domain->view();        # just $domain->name, and its types | 
| 593 |  |  |  |  |  |  | $posts   = $view->type( 'post' );  # just type post | 
| 594 |  |  |  |  |  |  |  | 
| 595 |  |  |  |  |  |  | 10 most relevant posts containing C<'perl'> or C<'moose'> | 
| 596 |  |  |  |  |  |  |  | 
| 597 |  |  |  |  |  |  | $results = $posts->queryb( content => 'perl moose' )->search; | 
| 598 |  |  |  |  |  |  |  | 
| 599 |  |  |  |  |  |  | 10 most relevant posts containing C<'perl'> or C<'moose'> published since | 
| 600 |  |  |  |  |  |  | 1 Jan 2012, sorted by C<timestamp>, with highlighted snippets from the | 
| 601 |  |  |  |  |  |  | C<content> field: | 
| 602 |  |  |  |  |  |  |  | 
| 603 |  |  |  |  |  |  | $results = $posts | 
| 604 |  |  |  |  |  |  | ->queryb    ( 'content' => 'perl moose'            ) | 
| 605 |  |  |  |  |  |  | ->filterb   ( 'created' => { gte => '2012-01-01' } ) | 
| 606 |  |  |  |  |  |  | ->sort      ( 'timestamp'                          ) | 
| 607 |  |  |  |  |  |  | ->highlight ( 'content'                            ) | 
| 608 |  |  |  |  |  |  | ->search; | 
| 609 |  |  |  |  |  |  |  | 
| 610 |  |  |  |  |  |  | The same as the above, but in one step: | 
| 611 |  |  |  |  |  |  |  | 
| 612 |  |  |  |  |  |  | $results = $domain->view( | 
| 613 |  |  |  |  |  |  | type             => 'post', | 
| 614 |  |  |  |  |  |  | sort             => 'timestamp', | 
| 615 |  |  |  |  |  |  | queryb           => { content => 'perl moose' }, | 
| 616 |  |  |  |  |  |  | filterb          => { created => { gte => '2012-01-01' } }, | 
| 617 |  |  |  |  |  |  | highlight        => 'content', | 
| 618 |  |  |  |  |  |  | )->search; | 
| 619 |  |  |  |  |  |  |  | 
| 620 |  |  |  |  |  |  | Efficiently retrieve all posts, unsorted: | 
| 621 |  |  |  |  |  |  |  | 
| 622 |  |  |  |  |  |  | $results = $posts->size(100)->scan; | 
| 623 |  |  |  |  |  |  |  | 
| 624 |  |  |  |  |  |  | while (my $result = $results->shift_result) { | 
| 625 |  |  |  |  |  |  | do_something_with($result); | 
| 626 |  |  |  |  |  |  | ); | 
| 627 |  |  |  |  |  |  |  | 
| 628 |  |  |  |  |  |  | Cached results: | 
| 629 |  |  |  |  |  |  |  | 
| 630 |  |  |  |  |  |  | $cache   = CHI->new(....); | 
| 631 |  |  |  |  |  |  | $view    = $view->cache( $cache )->cache_opts( expires_in => '2 min'); | 
| 632 |  |  |  |  |  |  |  | 
| 633 |  |  |  |  |  |  | $results = $view->queryb( 'perl' )->cached_search(); | 
| 634 |  |  |  |  |  |  | $results = $view->queryb( 'perl' )->cached_search( expires => '30 sec'); | 
| 635 |  |  |  |  |  |  |  | 
| 636 |  |  |  |  |  |  | =head1 DESCRIPTION | 
| 637 |  |  |  |  |  |  |  | 
| 638 |  |  |  |  |  |  | L<Elastic::Model::View> is used to query your docs in Elasticsearch. | 
| 639 |  |  |  |  |  |  |  | 
| 640 |  |  |  |  |  |  | Views are "chainable". In other words, you get a clone of the | 
| 641 |  |  |  |  |  |  | current view every time you set an attribute. For instance, you could do: | 
| 642 |  |  |  |  |  |  |  | 
| 643 |  |  |  |  |  |  | $all_types      = $domain->view; | 
| 644 |  |  |  |  |  |  | $users          = $all_types->type('user'); | 
| 645 |  |  |  |  |  |  | $posts          = $all_types->('post'); | 
| 646 |  |  |  |  |  |  | $recent_posts   = $posts->filterb({ published => { gt => '2012-05-01' }}); | 
| 647 |  |  |  |  |  |  |  | 
| 648 |  |  |  |  |  |  | Alternatively, you can set all or some of the attributes when you create | 
| 649 |  |  |  |  |  |  | a view: | 
| 650 |  |  |  |  |  |  |  | 
| 651 |  |  |  |  |  |  | $recent_posts   = $domain->view( | 
| 652 |  |  |  |  |  |  | type    => 'post', | 
| 653 |  |  |  |  |  |  | filterb => { published => { gt => '2012-05-01 '}} | 
| 654 |  |  |  |  |  |  | ); | 
| 655 |  |  |  |  |  |  |  | 
| 656 |  |  |  |  |  |  | Views are also reusable.  They only hit the database when you call one | 
| 657 |  |  |  |  |  |  | of the L<methods|/METHODS>, eg: | 
| 658 |  |  |  |  |  |  |  | 
| 659 |  |  |  |  |  |  | $results        = $recent_posts->search;    # retrieve $size results | 
| 660 |  |  |  |  |  |  | $scroll         = $recent_posts->scroll;    # keep pulling results | 
| 661 |  |  |  |  |  |  |  | 
| 662 |  |  |  |  |  |  | =head1 METHODS | 
| 663 |  |  |  |  |  |  |  | 
| 664 |  |  |  |  |  |  | Calling one of the methods listed below executes your query and returns | 
| 665 |  |  |  |  |  |  | the results.  Your C<view> is unchanged and can be reused later. | 
| 666 |  |  |  |  |  |  |  | 
| 667 |  |  |  |  |  |  | See L<Elastic::Manual::Searching> for a discussion about when | 
| 668 |  |  |  |  |  |  | and how to use L</search()>, L</scroll()> or L</scan()>. | 
| 669 |  |  |  |  |  |  |  | 
| 670 |  |  |  |  |  |  | =head2 search() | 
| 671 |  |  |  |  |  |  |  | 
| 672 |  |  |  |  |  |  | $results = $view->search(); | 
| 673 |  |  |  |  |  |  |  | 
| 674 |  |  |  |  |  |  | Executes a search and returns an L<Elastic::Model::Results> object | 
| 675 |  |  |  |  |  |  | with at most L</size> results. | 
| 676 |  |  |  |  |  |  |  | 
| 677 |  |  |  |  |  |  | This is useful for returning finite results, ie where you know how many | 
| 678 |  |  |  |  |  |  | results you want.  For instance: I<"give me the 10 best results">. | 
| 679 |  |  |  |  |  |  |  | 
| 680 |  |  |  |  |  |  | =head2 cached_search() | 
| 681 |  |  |  |  |  |  |  | 
| 682 |  |  |  |  |  |  | B<NOTE: Think carefully before you cache data outside of Elasticsearch. | 
| 683 |  |  |  |  |  |  | Elasticsearch already has smart filter caches, which are updated as your data | 
| 684 |  |  |  |  |  |  | changes. Most of the time, you will be better off using those directly, | 
| 685 |  |  |  |  |  |  | instead of an external cache.> | 
| 686 |  |  |  |  |  |  |  | 
| 687 |  |  |  |  |  |  | $results = $view->cache( $cache )->cached_search( %opts ); | 
| 688 |  |  |  |  |  |  |  | 
| 689 |  |  |  |  |  |  | If a L</cache> attribute has been specified for the current view, then | 
| 690 |  |  |  |  |  |  | L</cached_search()> tries to retrieve the search results from the L</cache>. | 
| 691 |  |  |  |  |  |  | If it fails, then a L</search()> is executed, and the results are stored in | 
| 692 |  |  |  |  |  |  | the L</cache>. An L<Elastic::Model::Results::Cached> object is returned. | 
| 693 |  |  |  |  |  |  |  | 
| 694 |  |  |  |  |  |  | Any C<%opts> that are passed in override any default L</cache_opts>, and are | 
| 695 |  |  |  |  |  |  | passed to L<CHI's get() or set()|'https://metacpan.org/module/CHI#Getting-and-setting> | 
| 696 |  |  |  |  |  |  | methods. | 
| 697 |  |  |  |  |  |  |  | 
| 698 |  |  |  |  |  |  | $view    = $view->cache_opts( expires_in => '30 sec' ); | 
| 699 |  |  |  |  |  |  |  | 
| 700 |  |  |  |  |  |  | $results = $view->cached_search;                            # 30 seconds | 
| 701 |  |  |  |  |  |  | $results = $view->cached_search( expires_in => '2 min' );   #  2 minutes | 
| 702 |  |  |  |  |  |  |  | 
| 703 |  |  |  |  |  |  | Given the near-real-time nature of Elasticsearch, you sometimes want to | 
| 704 |  |  |  |  |  |  | invalidate a cached result in the near future.  For instance, if you have | 
| 705 |  |  |  |  |  |  | cached a list of comments on a blog post, but then you add a new comment, | 
| 706 |  |  |  |  |  |  | you want to invalidate the cached comments list.  However, the new | 
| 707 |  |  |  |  |  |  | comment will only become visible to search sometime within the next second, so | 
| 708 |  |  |  |  |  |  | invalidating the cache immediately may or may not be useful. | 
| 709 |  |  |  |  |  |  |  | 
| 710 |  |  |  |  |  |  | Use the special argument C<force_set> to bypass the cache C<get()> and to force | 
| 711 |  |  |  |  |  |  | the cached version to be updated, along with a new expiry time: | 
| 712 |  |  |  |  |  |  |  | 
| 713 |  |  |  |  |  |  | $results = $view->cached_search( force_set => 1, expires_in => '2 sec'); | 
| 714 |  |  |  |  |  |  |  | 
| 715 |  |  |  |  |  |  | =head2 scroll() | 
| 716 |  |  |  |  |  |  |  | 
| 717 |  |  |  |  |  |  | $scroll_timeout = '1m'; | 
| 718 |  |  |  |  |  |  | $scrolled_results = $view->scroll( $scroll_timeout ); | 
| 719 |  |  |  |  |  |  |  | 
| 720 |  |  |  |  |  |  | Executes a search and returns an L<Elastic::Model::Results::Scrolled> | 
| 721 |  |  |  |  |  |  | object which will pull L</size> results from Elasticsearch as required until | 
| 722 |  |  |  |  |  |  | either (1) no more results are available or (2) more than C<$scroll_timeout> | 
| 723 |  |  |  |  |  |  | (default 1 minute) elapses between requests to Elasticsearch. | 
| 724 |  |  |  |  |  |  |  | 
| 725 |  |  |  |  |  |  | Scrolling allows you to return an unbound result set.  Useful if you're not | 
| 726 |  |  |  |  |  |  | sure whether to expect 2 results or 2000. | 
| 727 |  |  |  |  |  |  |  | 
| 728 |  |  |  |  |  |  | =head2 scan() | 
| 729 |  |  |  |  |  |  |  | 
| 730 |  |  |  |  |  |  | $timeout = '1m'; | 
| 731 |  |  |  |  |  |  | $scrolled_results = $view->scan($timeout); | 
| 732 |  |  |  |  |  |  |  | 
| 733 |  |  |  |  |  |  | L</scan()> is a special type of L</scroll()> request, intended for efficient | 
| 734 |  |  |  |  |  |  | handling of large numbers of unsorted docs (eg when you want to reindex | 
| 735 |  |  |  |  |  |  | all of your data). | 
| 736 |  |  |  |  |  |  |  | 
| 737 |  |  |  |  |  |  | =head2 first() | 
| 738 |  |  |  |  |  |  |  | 
| 739 |  |  |  |  |  |  | $result = $view->first(); | 
| 740 |  |  |  |  |  |  | $object = $view->first->object; | 
| 741 |  |  |  |  |  |  |  | 
| 742 |  |  |  |  |  |  | Executes the search and returns just the first result.  All other | 
| 743 |  |  |  |  |  |  | metadata is thrown away. | 
| 744 |  |  |  |  |  |  |  | 
| 745 |  |  |  |  |  |  | =head2 total() | 
| 746 |  |  |  |  |  |  |  | 
| 747 |  |  |  |  |  |  | $total = $view->total(); | 
| 748 |  |  |  |  |  |  |  | 
| 749 |  |  |  |  |  |  | Executes the search and returns the total number of matching docs. | 
| 750 |  |  |  |  |  |  | All other metadta is thrown away. | 
| 751 |  |  |  |  |  |  |  | 
| 752 |  |  |  |  |  |  | =head2 delete() | 
| 753 |  |  |  |  |  |  |  | 
| 754 |  |  |  |  |  |  | $results = $view->delete(); | 
| 755 |  |  |  |  |  |  |  | 
| 756 |  |  |  |  |  |  | Deletes all docs matching the query and returns a hashref indicating | 
| 757 |  |  |  |  |  |  | success. Any docs that are stored in a live L<scope|Elastic::Model::Scope> | 
| 758 |  |  |  |  |  |  | or are cached somewhere are not removed. Any | 
| 759 |  |  |  |  |  |  | L<unique keys|Elastic::Manual::Attributes::Unique> are not removed. | 
| 760 |  |  |  |  |  |  |  | 
| 761 |  |  |  |  |  |  | This should really only be used once you are sure that the matching docs | 
| 762 |  |  |  |  |  |  | are out of circulation.  Also, it is more efficient to just delete a whole index | 
| 763 |  |  |  |  |  |  | (if possible), rather than deleting large numbers of docs. | 
| 764 |  |  |  |  |  |  |  | 
| 765 |  |  |  |  |  |  | B<Note:> The only attributes relevant to L</delete()> are L</domain>, | 
| 766 |  |  |  |  |  |  | L</type>, L</query>, L</routing>, L</consistency> and L</replication>. | 
| 767 |  |  |  |  |  |  |  | 
| 768 |  |  |  |  |  |  | =head1 CORE ATTRIBUTES | 
| 769 |  |  |  |  |  |  |  | 
| 770 |  |  |  |  |  |  | =head2 domain | 
| 771 |  |  |  |  |  |  |  | 
| 772 |  |  |  |  |  |  | $new_view = $view->domain('my_index'); | 
| 773 |  |  |  |  |  |  | $new_view = $view->domain('index_one','alias_two'); | 
| 774 |  |  |  |  |  |  |  | 
| 775 |  |  |  |  |  |  | \@domains = $view->domain; | 
| 776 |  |  |  |  |  |  |  | 
| 777 |  |  |  |  |  |  | Specify one or more domains (indices or aliases) to query. By default, a C<view> | 
| 778 |  |  |  |  |  |  | created from a L<domain|Elastic::Model::Domain> will query just that domain's | 
| 779 |  |  |  |  |  |  | L<name|Elastic::Model::Domain/name>. | 
| 780 |  |  |  |  |  |  | A C<view> created from the L<model|Elastic::Model::Role::Model> will query all | 
| 781 |  |  |  |  |  |  | the main domains (ie the L<Elastic::Model::Namespace/name>) and | 
| 782 |  |  |  |  |  |  | L<fixed domains|Elastic::Model::Namesapace/fixed domains> known to the model. | 
| 783 |  |  |  |  |  |  |  | 
| 784 |  |  |  |  |  |  | =head2 type | 
| 785 |  |  |  |  |  |  |  | 
| 786 |  |  |  |  |  |  | $new_view = $view->type('user'); | 
| 787 |  |  |  |  |  |  | $new_view = $view->type('user','post'); | 
| 788 |  |  |  |  |  |  |  | 
| 789 |  |  |  |  |  |  | \@types   = $view->type; | 
| 790 |  |  |  |  |  |  |  | 
| 791 |  |  |  |  |  |  | By default, a C<view> will query all L<types|Elastic::Manual::Terminology/Type> | 
| 792 |  |  |  |  |  |  | known to all the L<domains|"domain"> specified in the view.  You can specify | 
| 793 |  |  |  |  |  |  | one or more types. | 
| 794 |  |  |  |  |  |  |  | 
| 795 |  |  |  |  |  |  | =head2 query | 
| 796 |  |  |  |  |  |  |  | 
| 797 |  |  |  |  |  |  | =head2 queryb | 
| 798 |  |  |  |  |  |  |  | 
| 799 |  |  |  |  |  |  | # native query DSL | 
| 800 |  |  |  |  |  |  | $new_view = $view->query( text => { title => 'interesting words' } ); | 
| 801 |  |  |  |  |  |  |  | 
| 802 |  |  |  |  |  |  | # SearchBuilder DSL | 
| 803 |  |  |  |  |  |  | $new_view = $view->queryb( title => 'interesting words' ); | 
| 804 |  |  |  |  |  |  |  | 
| 805 |  |  |  |  |  |  | \%query   = $view->query | 
| 806 |  |  |  |  |  |  |  | 
| 807 |  |  |  |  |  |  | Specify the query to run in the native | 
| 808 |  |  |  |  |  |  | L<Elasticsearch query DSL|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl.html> | 
| 809 |  |  |  |  |  |  | or use C<queryb()> to specify your query  with the more Perlish | 
| 810 |  |  |  |  |  |  | L<Elastic::Model::SearchBuilder> query syntax. | 
| 811 |  |  |  |  |  |  |  | 
| 812 |  |  |  |  |  |  | By default, the query will | 
| 813 |  |  |  |  |  |  | L<match all docs|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-match-all-query.html>. | 
| 814 |  |  |  |  |  |  |  | 
| 815 |  |  |  |  |  |  | =head2 filter | 
| 816 |  |  |  |  |  |  |  | 
| 817 |  |  |  |  |  |  | =head2 filterb | 
| 818 |  |  |  |  |  |  |  | 
| 819 |  |  |  |  |  |  | # native query DSL | 
| 820 |  |  |  |  |  |  | $new_view = $view->filter( term => { tag => 'perl' } ); | 
| 821 |  |  |  |  |  |  |  | 
| 822 |  |  |  |  |  |  | # SearchBuilder DSL | 
| 823 |  |  |  |  |  |  | $new_view = $view->filterb( tag => 'perl' ); | 
| 824 |  |  |  |  |  |  |  | 
| 825 |  |  |  |  |  |  | \%filter  = $view->filter; | 
| 826 |  |  |  |  |  |  |  | 
| 827 |  |  |  |  |  |  | You can specify a filter to apply to the query results using either | 
| 828 |  |  |  |  |  |  | the native Elasticsearch query DSL or, use C<filterb()> to specify your | 
| 829 |  |  |  |  |  |  | filter with the more Perlish L<Elastic::Model::SearchBuilder> DSL. | 
| 830 |  |  |  |  |  |  | If a filter is specified, it will be combined with the L</query> | 
| 831 |  |  |  |  |  |  | as a L<filtered query|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-filtered-query.html>, | 
| 832 |  |  |  |  |  |  | or (if no query is specified) as a | 
| 833 |  |  |  |  |  |  | L<constant score|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/query-dsl-constant-score-query.html> | 
| 834 |  |  |  |  |  |  | query. | 
| 835 |  |  |  |  |  |  |  | 
| 836 |  |  |  |  |  |  | =head2 post_filter | 
| 837 |  |  |  |  |  |  |  | 
| 838 |  |  |  |  |  |  | =head2 post_filterb | 
| 839 |  |  |  |  |  |  |  | 
| 840 |  |  |  |  |  |  | # native query DSL | 
| 841 |  |  |  |  |  |  | $new_view = $view->post_filter( term => { tag => 'perl' } ); | 
| 842 |  |  |  |  |  |  |  | 
| 843 |  |  |  |  |  |  | # SearchBuilder DSL | 
| 844 |  |  |  |  |  |  | $new_view = $view->post_filterb( tag => 'perl' ); | 
| 845 |  |  |  |  |  |  |  | 
| 846 |  |  |  |  |  |  | \%filter  = $view->post_filter; | 
| 847 |  |  |  |  |  |  |  | 
| 848 |  |  |  |  |  |  | L<Post-filters|http://www.elasticsearch.org/guide/en/elasticsearch/reference/0.90/search-request-post-filter.html> | 
| 849 |  |  |  |  |  |  | filter the results AFTER any L</aggs> have been calculated.  In the above | 
| 850 |  |  |  |  |  |  | example, the aggregations would be calculated on all values of C<tag>, but the | 
| 851 |  |  |  |  |  |  | results would then be limited to just those docs where C<tag == perl>. | 
| 852 |  |  |  |  |  |  |  | 
| 853 |  |  |  |  |  |  | You can specify a post_filter using either the native Elasticsearch query DSL or, | 
| 854 |  |  |  |  |  |  | use C<post_filterb()> to specify it with the more Perlish | 
| 855 |  |  |  |  |  |  | L<Elastic::Model::SearchBuilder> DSL. | 
| 856 |  |  |  |  |  |  |  | 
| 857 |  |  |  |  |  |  | =head2 sort | 
| 858 |  |  |  |  |  |  |  | 
| 859 |  |  |  |  |  |  | $new_view = $view->sort( '_score'                ); # _score desc | 
| 860 |  |  |  |  |  |  | $new_view = $view->sort( 'timestamp'             ); # timestamp asc | 
| 861 |  |  |  |  |  |  | $new_view = $view->sort( { timestamp => 'asc' }  ); # timestamp asc | 
| 862 |  |  |  |  |  |  | $new_view = $view->sort( { timestamp => 'desc' } ); # timestamp desc | 
| 863 |  |  |  |  |  |  |  | 
| 864 |  |  |  |  |  |  | $new_view = $view->sort( | 
| 865 |  |  |  |  |  |  | '_score',                                       # _score desc | 
| 866 |  |  |  |  |  |  | { timestamp => 'desc' }                         # then timestamp desc | 
| 867 |  |  |  |  |  |  | ); | 
| 868 |  |  |  |  |  |  |  | 
| 869 |  |  |  |  |  |  | \@sort    = $view->sort | 
| 870 |  |  |  |  |  |  |  | 
| 871 |  |  |  |  |  |  | By default, results are sorted by "relevance" (C<< _score => 'desc' >>). | 
| 872 |  |  |  |  |  |  | You can specify multiple sort arguments, which are applied in order, and | 
| 873 |  |  |  |  |  |  | can include scripts or geo-distance. | 
| 874 |  |  |  |  |  |  | See L<http://www.elasticsearch.org/guide/en/elasticsearch/reference/0.90/search-request-sort.html> for | 
| 875 |  |  |  |  |  |  | more information. | 
| 876 |  |  |  |  |  |  |  | 
| 877 |  |  |  |  |  |  | B<Note:> Sorting cannot be combined with L</scan()>. | 
| 878 |  |  |  |  |  |  |  | 
| 879 |  |  |  |  |  |  | =head2 from | 
| 880 |  |  |  |  |  |  |  | 
| 881 |  |  |  |  |  |  | $new_view = $view->from( 10 ); | 
| 882 |  |  |  |  |  |  |  | 
| 883 |  |  |  |  |  |  | $from     = $view->from; | 
| 884 |  |  |  |  |  |  |  | 
| 885 |  |  |  |  |  |  | By default, results are returned from the first result. Think of it as | 
| 886 |  |  |  |  |  |  | I<"the number of docs to skip">, so setting C<from> to C<0> would start from | 
| 887 |  |  |  |  |  |  | the first result. Setting C<from> to C<10> would skip the first 10 results | 
| 888 |  |  |  |  |  |  | and return docs from result number 11 onwards. | 
| 889 |  |  |  |  |  |  |  | 
| 890 |  |  |  |  |  |  | =head2 size | 
| 891 |  |  |  |  |  |  |  | 
| 892 |  |  |  |  |  |  | $new_view = $view->size( 100 ); | 
| 893 |  |  |  |  |  |  |  | 
| 894 |  |  |  |  |  |  | $size     = $view->size; | 
| 895 |  |  |  |  |  |  |  | 
| 896 |  |  |  |  |  |  | The number of results returned in a single L</search()>, which defaults to 10. | 
| 897 |  |  |  |  |  |  |  | 
| 898 |  |  |  |  |  |  | B<Note:> See L</scan()> for a slightly different application of the L</size> | 
| 899 |  |  |  |  |  |  | value. | 
| 900 |  |  |  |  |  |  |  | 
| 901 |  |  |  |  |  |  | =head2 aggs | 
| 902 |  |  |  |  |  |  |  | 
| 903 |  |  |  |  |  |  | $new_view = $view->aggs( | 
| 904 |  |  |  |  |  |  | active_docs => { | 
| 905 |  |  |  |  |  |  | filter => { | 
| 906 |  |  |  |  |  |  | term => { status => 'active' } | 
| 907 |  |  |  |  |  |  | }, | 
| 908 |  |  |  |  |  |  | aggs => { | 
| 909 |  |  |  |  |  |  | popular_tags => { | 
| 910 |  |  |  |  |  |  | terms => { | 
| 911 |  |  |  |  |  |  | field => 'path.to.tags', | 
| 912 |  |  |  |  |  |  | size  => 10 | 
| 913 |  |  |  |  |  |  | } | 
| 914 |  |  |  |  |  |  | } | 
| 915 |  |  |  |  |  |  | } | 
| 916 |  |  |  |  |  |  | }, | 
| 917 |  |  |  |  |  |  | agg_two => {....} | 
| 918 |  |  |  |  |  |  | ); | 
| 919 |  |  |  |  |  |  |  | 
| 920 |  |  |  |  |  |  | $new_view = $view->add_agg( agg_three => {...} ) | 
| 921 |  |  |  |  |  |  | $new_view = $view->remove_agg('agg_three'); | 
| 922 |  |  |  |  |  |  |  | 
| 923 |  |  |  |  |  |  | \%aggs  = $view->aggs; | 
| 924 |  |  |  |  |  |  | \%agg   = $view->get_agg('active_docs'); | 
| 925 |  |  |  |  |  |  |  | 
| 926 |  |  |  |  |  |  | Aggregations allow you to aggregate data from a query, for instance: most popular | 
| 927 |  |  |  |  |  |  | terms, number of blog posts per day, average price etc. Aggs are calculated | 
| 928 |  |  |  |  |  |  | from the query generated from L</query> and L</filter>.  If you want to filter | 
| 929 |  |  |  |  |  |  | your query results down further after calculating your aggs, you can | 
| 930 |  |  |  |  |  |  | use L</post_filter>. | 
| 931 |  |  |  |  |  |  |  | 
| 932 |  |  |  |  |  |  | B<NOTE:> There is no support in aggs for L<Elastic::Model::SearchBuilder>. | 
| 933 |  |  |  |  |  |  |  | 
| 934 |  |  |  |  |  |  | See L<http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-aggregations.html> for | 
| 935 |  |  |  |  |  |  | an explanation of what aggregations are available. | 
| 936 |  |  |  |  |  |  |  | 
| 937 |  |  |  |  |  |  | =head2 facets | 
| 938 |  |  |  |  |  |  |  | 
| 939 |  |  |  |  |  |  | B<IMPORTANT:> Facets are deprecated in favour of L<aggregations|/aggs>. | 
| 940 |  |  |  |  |  |  | They will be removed in a future version of Elasticsearch. | 
| 941 |  |  |  |  |  |  |  | 
| 942 |  |  |  |  |  |  | $new_view = $view->facets( | 
| 943 |  |  |  |  |  |  | facet_one => { | 
| 944 |  |  |  |  |  |  | terms   => { | 
| 945 |  |  |  |  |  |  | field => 'field.to.facet', | 
| 946 |  |  |  |  |  |  | size  => 10 | 
| 947 |  |  |  |  |  |  | }, | 
| 948 |  |  |  |  |  |  | facet_filterb => { status => 'active' }, | 
| 949 |  |  |  |  |  |  | }, | 
| 950 |  |  |  |  |  |  | facet_two => {....} | 
| 951 |  |  |  |  |  |  | ); | 
| 952 |  |  |  |  |  |  |  | 
| 953 |  |  |  |  |  |  | $new_view = $view->add_facet( facet_three => {...} ) | 
| 954 |  |  |  |  |  |  | $new_view = $view->remove_facet('facet_three'); | 
| 955 |  |  |  |  |  |  |  | 
| 956 |  |  |  |  |  |  | \%facets  = $view->facets; | 
| 957 |  |  |  |  |  |  | \%facet   = $view->get_facet('facet_one'); | 
| 958 |  |  |  |  |  |  |  | 
| 959 |  |  |  |  |  |  | Facets allow you to aggregate data from a query, for instance: most popular | 
| 960 |  |  |  |  |  |  | terms, number of blog posts per day, average price etc. Facets are calculated | 
| 961 |  |  |  |  |  |  | from the query generated from L</query> and L</filter>.  If you want to filter | 
| 962 |  |  |  |  |  |  | your query results down further after calculating your facets, you can | 
| 963 |  |  |  |  |  |  | use L</post_filter>. | 
| 964 |  |  |  |  |  |  |  | 
| 965 |  |  |  |  |  |  | See L<http://www.elasticsearch.org/guide/en/elasticsearch/reference/0.90/search-facets.html> for | 
| 966 |  |  |  |  |  |  | an explanation of what facets are available. | 
| 967 |  |  |  |  |  |  |  | 
| 968 |  |  |  |  |  |  | =head2 highlight | 
| 969 |  |  |  |  |  |  |  | 
| 970 |  |  |  |  |  |  | $new_view = $view->highlight( | 
| 971 |  |  |  |  |  |  | 'field_1', | 
| 972 |  |  |  |  |  |  | 'field_2' => \%field_2_settings, | 
| 973 |  |  |  |  |  |  | 'field_3' | 
| 974 |  |  |  |  |  |  | ); | 
| 975 |  |  |  |  |  |  |  | 
| 976 |  |  |  |  |  |  | Specify which fields should be used for | 
| 977 |  |  |  |  |  |  | L<highlighted snippets|http://www.elasticsearch.org/guide/en/elasticsearch/reference/0.90/search-request-highlighting.html>. | 
| 978 |  |  |  |  |  |  | to your search results. You can pass just a list of fields, or fields with | 
| 979 |  |  |  |  |  |  | their field-specific settings. These values are used to set the C<fields> | 
| 980 |  |  |  |  |  |  | parameter in L</highlighting>. | 
| 981 |  |  |  |  |  |  |  | 
| 982 |  |  |  |  |  |  | =head2 highlighting | 
| 983 |  |  |  |  |  |  |  | 
| 984 |  |  |  |  |  |  | $new_view = $view->highlighting( | 
| 985 |  |  |  |  |  |  | pre_tags    =>  [ '<em>',  '<b>'  ], | 
| 986 |  |  |  |  |  |  | post_tags   =>  [ '</em>', '</b>' ], | 
| 987 |  |  |  |  |  |  | encoder     => 'html' | 
| 988 |  |  |  |  |  |  | ... | 
| 989 |  |  |  |  |  |  | ); | 
| 990 |  |  |  |  |  |  |  | 
| 991 |  |  |  |  |  |  | The L</highlighting> attribute is used to pass any highlighting parameters | 
| 992 |  |  |  |  |  |  | which should be applied to all of the fields set in L</highlight> (although | 
| 993 |  |  |  |  |  |  | you can override these settings for individual fields by passing field settings | 
| 994 |  |  |  |  |  |  | to L</highlight>). | 
| 995 |  |  |  |  |  |  |  | 
| 996 |  |  |  |  |  |  | See L<http://www.elasticsearch.org/guide/en/elasticsearch/reference/0.90/search-request-highlighting.html>. | 
| 997 |  |  |  |  |  |  | for more about how highlighting works, and L<Elastic::Model::Result/highlight> | 
| 998 |  |  |  |  |  |  | for how to retrieve the highlighted snippets. | 
| 999 |  |  |  |  |  |  |  | 
| 1000 |  |  |  |  |  |  | =head1 OTHER ATTRIBUTES | 
| 1001 |  |  |  |  |  |  |  | 
| 1002 |  |  |  |  |  |  | =head2 fields | 
| 1003 |  |  |  |  |  |  |  | 
| 1004 |  |  |  |  |  |  | $new_view = $view->fields('title','content'); | 
| 1005 |  |  |  |  |  |  |  | 
| 1006 |  |  |  |  |  |  | By default, searches will return the L<_source|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/mapping-source-field.html> | 
| 1007 |  |  |  |  |  |  | field which contains the whole document, allowing Elastic::Model to inflate | 
| 1008 |  |  |  |  |  |  | the original object without having to retrieve the document separately. If you | 
| 1009 |  |  |  |  |  |  | would like to just retrieve a subset of fields, you can specify them in | 
| 1010 |  |  |  |  |  |  | L</fields>. See L<http://www.elasticsearch.org/guide/en/elasticsearch/reference/0.90/search-request-fields.html>. | 
| 1011 |  |  |  |  |  |  |  | 
| 1012 |  |  |  |  |  |  | B<Note:> If you do specify any fields, and you DON'T include C<'_source'> then the | 
| 1013 |  |  |  |  |  |  | C<_source> field won't be returned, and you won't be able to retrieve the original | 
| 1014 |  |  |  |  |  |  | object without requesting it from Elasticsearch in a separate (but automatic) step. | 
| 1015 |  |  |  |  |  |  |  | 
| 1016 |  |  |  |  |  |  | =head2 script_fields | 
| 1017 |  |  |  |  |  |  |  | 
| 1018 |  |  |  |  |  |  | $new_view = $view->script_fields( | 
| 1019 |  |  |  |  |  |  | distance => { | 
| 1020 |  |  |  |  |  |  | script  => q{doc['location'].distance(lat,lon)}, | 
| 1021 |  |  |  |  |  |  | params  => { lat => $lat, lon => $lon } | 
| 1022 |  |  |  |  |  |  | }, | 
| 1023 |  |  |  |  |  |  | $name    => \%defn, | 
| 1024 |  |  |  |  |  |  | ... | 
| 1025 |  |  |  |  |  |  | ); | 
| 1026 |  |  |  |  |  |  |  | 
| 1027 |  |  |  |  |  |  | $new_view = $view->add_script_field( $name => \%defn ); | 
| 1028 |  |  |  |  |  |  | $new_view = $view->remove_script_field($name); | 
| 1029 |  |  |  |  |  |  |  | 
| 1030 |  |  |  |  |  |  | \%fields  = $view->script_fields; | 
| 1031 |  |  |  |  |  |  | \%defn    = $view->get_script_field($name); | 
| 1032 |  |  |  |  |  |  |  | 
| 1033 |  |  |  |  |  |  | L<Script fields|http://www.elasticsearch.org/guide/en/elasticsearch/reference/0.90/search-request-script-fields.html> | 
| 1034 |  |  |  |  |  |  | can be generated using the L<mvel|http://mvel.codehaus.org/Language+Guide+for+2.0> | 
| 1035 |  |  |  |  |  |  | scripting language. (You can also use L<Groovy, Javascript, Python and Java|http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/modules-scripting.html>.) | 
| 1036 |  |  |  |  |  |  |  | 
| 1037 |  |  |  |  |  |  | =head2 include_paths / exclude_paths | 
| 1038 |  |  |  |  |  |  |  | 
| 1039 |  |  |  |  |  |  | $new_view    = $view->include_paths('foo.*') | 
| 1040 |  |  |  |  |  |  | ->exclude_paths('foo.bar.*','baz.*'); | 
| 1041 |  |  |  |  |  |  |  | 
| 1042 |  |  |  |  |  |  | $results     = $new_view->search->as_partials; | 
| 1043 |  |  |  |  |  |  | $partial_obj = $results->next; | 
| 1044 |  |  |  |  |  |  |  | 
| 1045 |  |  |  |  |  |  | If your objects are large, but you only need access to a few attributes to | 
| 1046 |  |  |  |  |  |  | eg display search results, you may want to retrieve only the relevant parts of | 
| 1047 |  |  |  |  |  |  | each object.  You can specify which parts of the object to include or exclude | 
| 1048 |  |  |  |  |  |  | using C<include_paths> and C<exclude_paths>. If either of these is set | 
| 1049 |  |  |  |  |  |  | then the full C<_source> field will not be loaded (unless you specify it | 
| 1050 |  |  |  |  |  |  | explicitly using L</fields>). | 
| 1051 |  |  |  |  |  |  |  | 
| 1052 |  |  |  |  |  |  | The partial objects returned when L<Elastic::Model::Results/as_partials()> | 
| 1053 |  |  |  |  |  |  | is in effect function exactly as real objects, except that they cannot | 
| 1054 |  |  |  |  |  |  | be saved. | 
| 1055 |  |  |  |  |  |  |  | 
| 1056 |  |  |  |  |  |  | See L<http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-source-filtering.html>. | 
| 1057 |  |  |  |  |  |  |  | 
| 1058 |  |  |  |  |  |  | =head2 routing | 
| 1059 |  |  |  |  |  |  |  | 
| 1060 |  |  |  |  |  |  | $new_view = $view->routing( 'routing_val' ); | 
| 1061 |  |  |  |  |  |  | $new_view = $view->routing( 'routing_1', 'routing_2' ); | 
| 1062 |  |  |  |  |  |  |  | 
| 1063 |  |  |  |  |  |  | Search queries are usually directed at all shards. If you are using routing | 
| 1064 |  |  |  |  |  |  | (eg to store related docs on the same shard) then you can limit the search | 
| 1065 |  |  |  |  |  |  | to just the relevant shard(s). B<Note:> if you are searching on aliases that | 
| 1066 |  |  |  |  |  |  | have routing configured, then specifying a L</routing> manually will override | 
| 1067 |  |  |  |  |  |  | those values. | 
| 1068 |  |  |  |  |  |  |  | 
| 1069 |  |  |  |  |  |  | See L<Elastic::Manual::Scaling> for more. | 
| 1070 |  |  |  |  |  |  |  | 
| 1071 |  |  |  |  |  |  | =head2 index_boosts | 
| 1072 |  |  |  |  |  |  |  | 
| 1073 |  |  |  |  |  |  | $new_view = $view->index_boosts( | 
| 1074 |  |  |  |  |  |  | index_1 => 4, | 
| 1075 |  |  |  |  |  |  | index_2 => 2 | 
| 1076 |  |  |  |  |  |  | ); | 
| 1077 |  |  |  |  |  |  |  | 
| 1078 |  |  |  |  |  |  | $new_view = $view->add_index_boost( $index => $boost ); | 
| 1079 |  |  |  |  |  |  | $new_view = $view->remove_index_boost( $index ); | 
| 1080 |  |  |  |  |  |  |  | 
| 1081 |  |  |  |  |  |  | \%boosts  = $view->index_boosts; | 
| 1082 |  |  |  |  |  |  | $boost    = $view->get_index_boost( $index ); | 
| 1083 |  |  |  |  |  |  |  | 
| 1084 |  |  |  |  |  |  | Make results from one index more relevant than those from another index. | 
| 1085 |  |  |  |  |  |  |  | 
| 1086 |  |  |  |  |  |  | =head2 min_score | 
| 1087 |  |  |  |  |  |  |  | 
| 1088 |  |  |  |  |  |  | $new_view  = $view->min_score( 2 ); | 
| 1089 |  |  |  |  |  |  | $min_score = $view->min_score; | 
| 1090 |  |  |  |  |  |  |  | 
| 1091 |  |  |  |  |  |  | Exclude results whose score (relevance) is less than the specified number. | 
| 1092 |  |  |  |  |  |  |  | 
| 1093 |  |  |  |  |  |  | =head2 preference | 
| 1094 |  |  |  |  |  |  |  | 
| 1095 |  |  |  |  |  |  | $new_view = $view->preference( '_local' ); | 
| 1096 |  |  |  |  |  |  |  | 
| 1097 |  |  |  |  |  |  | Control which node should return search results. See | 
| 1098 |  |  |  |  |  |  | L<http://www.elasticsearch.org/guide/en/elasticsearch/reference/current/search-request-preference.html> for more. | 
| 1099 |  |  |  |  |  |  |  | 
| 1100 |  |  |  |  |  |  | =head2 timeout | 
| 1101 |  |  |  |  |  |  |  | 
| 1102 |  |  |  |  |  |  | $new_view = $view->timeout( 10 );         # 10 ms | 
| 1103 |  |  |  |  |  |  | $new_view = $view->timeout( '10s' );      # 10 sec | 
| 1104 |  |  |  |  |  |  |  | 
| 1105 |  |  |  |  |  |  | $timeout  = $view->timeout; | 
| 1106 |  |  |  |  |  |  |  | 
| 1107 |  |  |  |  |  |  | Sets an upper limit on the the time to wait for search results, returning | 
| 1108 |  |  |  |  |  |  | with whatever results it has managed to receive up until that point. | 
| 1109 |  |  |  |  |  |  |  | 
| 1110 |  |  |  |  |  |  | =head2 track_scores | 
| 1111 |  |  |  |  |  |  |  | 
| 1112 |  |  |  |  |  |  | $new_view = $view->track_scores( 1 ); | 
| 1113 |  |  |  |  |  |  | $track    = $view->track_scores; | 
| 1114 |  |  |  |  |  |  |  | 
| 1115 |  |  |  |  |  |  | By default, If you sort on a field other than C<_score>, Elasticsearch | 
| 1116 |  |  |  |  |  |  | does not return the calculated relevance score for each doc.  If | 
| 1117 |  |  |  |  |  |  | L</track_scores> is true, these scores will be returned regardless. | 
| 1118 |  |  |  |  |  |  |  | 
| 1119 |  |  |  |  |  |  | =head1 CACHING ATTRIBUTES | 
| 1120 |  |  |  |  |  |  |  | 
| 1121 |  |  |  |  |  |  | Bounded searches (those returned by calling L</search()>) can be stored | 
| 1122 |  |  |  |  |  |  | in a L<CHI>-compatible cache. | 
| 1123 |  |  |  |  |  |  |  | 
| 1124 |  |  |  |  |  |  | =head2 cache | 
| 1125 |  |  |  |  |  |  |  | 
| 1126 |  |  |  |  |  |  | $cache    = CHI->new(...); | 
| 1127 |  |  |  |  |  |  | $new_view = $view->cache( $cache ); | 
| 1128 |  |  |  |  |  |  |  | 
| 1129 |  |  |  |  |  |  | Stores an instance of a L<CHI>-compatible cache, to be used with | 
| 1130 |  |  |  |  |  |  | L</cached_search()>. | 
| 1131 |  |  |  |  |  |  |  | 
| 1132 |  |  |  |  |  |  | =head2 cache_opts | 
| 1133 |  |  |  |  |  |  |  | 
| 1134 |  |  |  |  |  |  | $new_view = $view->cache_opts( expires_in => '20 sec', ...); | 
| 1135 |  |  |  |  |  |  |  | 
| 1136 |  |  |  |  |  |  | Stores the default options that should be passed to | 
| 1137 |  |  |  |  |  |  | L<CHI's get() or set()|'https://metacpan.org/module/CHI#Getting-and-setting>. | 
| 1138 |  |  |  |  |  |  | These can be overridden by passing options to L</cached_search()>. | 
| 1139 |  |  |  |  |  |  |  | 
| 1140 |  |  |  |  |  |  | =head1 DEBUGGING ATTRIBUTES | 
| 1141 |  |  |  |  |  |  |  | 
| 1142 |  |  |  |  |  |  | =head2 explain | 
| 1143 |  |  |  |  |  |  |  | 
| 1144 |  |  |  |  |  |  | $new_view = $view->explain( 1 ); | 
| 1145 |  |  |  |  |  |  | $explain  = $view->explain; | 
| 1146 |  |  |  |  |  |  |  | 
| 1147 |  |  |  |  |  |  | Set L</explain> to true to return debugging information explaining how | 
| 1148 |  |  |  |  |  |  | each document's score was calculated. See | 
| 1149 |  |  |  |  |  |  | L<Elastic::Model::Result/explain> to view the output. | 
| 1150 |  |  |  |  |  |  |  | 
| 1151 |  |  |  |  |  |  | =head2 stats | 
| 1152 |  |  |  |  |  |  |  | 
| 1153 |  |  |  |  |  |  | $new_view = $view->stats( 'group_1', 'group_2' ); | 
| 1154 |  |  |  |  |  |  | \@groups  = $view->stats; | 
| 1155 |  |  |  |  |  |  |  | 
| 1156 |  |  |  |  |  |  | The statistics for each search can be aggregated by C<group>. These stats | 
| 1157 |  |  |  |  |  |  | can later be retrieved using L<Search::Elasticsearch::Client::Direct::Indices/stats()>. | 
| 1158 |  |  |  |  |  |  |  | 
| 1159 |  |  |  |  |  |  | =head2 search_builder | 
| 1160 |  |  |  |  |  |  |  | 
| 1161 |  |  |  |  |  |  | $new_view = $view->search_builder( $search_builder ); | 
| 1162 |  |  |  |  |  |  | $builder  = $view->search_builder; | 
| 1163 |  |  |  |  |  |  |  | 
| 1164 |  |  |  |  |  |  | If you would like to use a different search builder than the default | 
| 1165 |  |  |  |  |  |  | L<Elastic::Model::SearchBuilder> for L</"queryb">, L</"filterb"> or | 
| 1166 |  |  |  |  |  |  | L</post_filterb>, then you can set a value for L</search_builder>. | 
| 1167 |  |  |  |  |  |  |  | 
| 1168 |  |  |  |  |  |  | =head1 DELETE ATTRIBUTES | 
| 1169 |  |  |  |  |  |  |  | 
| 1170 |  |  |  |  |  |  | These parameters are only used with L</delete()>. | 
| 1171 |  |  |  |  |  |  |  | 
| 1172 |  |  |  |  |  |  | =head2 consistency | 
| 1173 |  |  |  |  |  |  |  | 
| 1174 |  |  |  |  |  |  | $new_view    = $view->consistency( 'quorum' | 'all' | 'one' ); | 
| 1175 |  |  |  |  |  |  | $consistency = $view->consistency; | 
| 1176 |  |  |  |  |  |  |  | 
| 1177 |  |  |  |  |  |  | At least C<one>, C<all> or a C<quorum> (default) of nodes must be present for | 
| 1178 |  |  |  |  |  |  | the delete to take place. | 
| 1179 |  |  |  |  |  |  |  | 
| 1180 |  |  |  |  |  |  | =head2 replication | 
| 1181 |  |  |  |  |  |  |  | 
| 1182 |  |  |  |  |  |  | $new_view    = $view->replication( 'sync' | 'async' ); | 
| 1183 |  |  |  |  |  |  | $replication = $view->replication; | 
| 1184 |  |  |  |  |  |  |  | 
| 1185 |  |  |  |  |  |  | Should a delete be done synchronously (ie waits until all nodes within | 
| 1186 |  |  |  |  |  |  | the replcation group have run the delete) or asynchronously (returns | 
| 1187 |  |  |  |  |  |  | immediately, and performs the delete in the background). | 
| 1188 |  |  |  |  |  |  |  | 
| 1189 |  |  |  |  |  |  | =head1 AUTHOR | 
| 1190 |  |  |  |  |  |  |  | 
| 1191 |  |  |  |  |  |  | Clinton Gormley <drtech@cpan.org> | 
| 1192 |  |  |  |  |  |  |  | 
| 1193 |  |  |  |  |  |  | =head1 COPYRIGHT AND LICENSE | 
| 1194 |  |  |  |  |  |  |  | 
| 1195 |  |  |  |  |  |  | This software is copyright (c) 2015 by Clinton Gormley. | 
| 1196 |  |  |  |  |  |  |  | 
| 1197 |  |  |  |  |  |  | This is free software; you can redistribute it and/or modify it under | 
| 1198 |  |  |  |  |  |  | the same terms as the Perl 5 programming language system itself. | 
| 1199 |  |  |  |  |  |  |  | 
| 1200 |  |  |  |  |  |  | =cut | 
| 1201 |  |  |  |  |  |  |  | 
| 1202 |  |  |  |  |  |  | __END__ | 
| 1203 |  |  |  |  |  |  |  | 
| 1204 |  |  |  |  |  |  | # ABSTRACT: Views to query your docs in Elasticsearch | 
| 1205 |  |  |  |  |  |  |  | 
| 1206 |  |  |  |  |  |  |  |