| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | # | 
| 2 |  |  |  |  |  |  | # This file is part of ElasticSearchX-Model | 
| 3 |  |  |  |  |  |  | # | 
| 4 |  |  |  |  |  |  | # This software is Copyright (c) 2016 by Moritz Onken. | 
| 5 |  |  |  |  |  |  | # | 
| 6 |  |  |  |  |  |  | # This is free software, licensed under: | 
| 7 |  |  |  |  |  |  | # | 
| 8 |  |  |  |  |  |  | #   The (three-clause) BSD License | 
| 9 |  |  |  |  |  |  | # | 
| 10 |  |  |  |  |  |  | package ElasticSearchX::Model::Document::Set; | 
| 11 |  |  |  |  |  |  | $ElasticSearchX::Model::Document::Set::VERSION = '1.0.2'; | 
| 12 |  |  |  |  |  |  | # ABSTRACT: Represents a query used for fetching a set of results | 
| 13 | 2 |  |  | 2 |  | 1133 | use Moose; | 
|  | 2 |  |  |  |  | 3 |  | 
|  | 2 |  |  |  |  | 12 |  | 
| 14 | 2 |  |  | 2 |  | 9345 | use MooseX::Attribute::Chained; | 
|  | 2 |  |  |  |  | 9573 |  | 
|  | 2 |  |  |  |  | 47 |  | 
| 15 | 2 |  |  | 2 |  | 851 | use MooseX::Attribute::ChainedClone; | 
|  | 2 |  |  |  |  | 8284 |  | 
|  | 2 |  |  |  |  | 59 |  | 
| 16 | 2 |  |  | 2 |  | 766 | use ElasticSearchX::Model::Scroll; | 
|  | 2 |  |  |  |  | 516 |  | 
|  | 2 |  |  |  |  | 74 |  | 
| 17 | 2 |  |  | 2 |  | 11 | use ElasticSearchX::Model::Document::Types qw(:all); | 
|  | 2 |  |  |  |  | 3 |  | 
|  | 2 |  |  |  |  | 19 |  | 
| 18 |  |  |  |  |  |  |  | 
| 19 |  |  |  |  |  |  | has type => ( is => 'ro', required => 1 ); | 
| 20 |  |  |  |  |  |  | has index => ( is => 'ro', required => 1, handles => [qw(es model)] ); | 
| 21 |  |  |  |  |  |  |  | 
| 22 |  |  |  |  |  |  | has query => ( | 
| 23 |  |  |  |  |  |  | isa    => 'HashRef', | 
| 24 |  |  |  |  |  |  | is     => 'rw', | 
| 25 |  |  |  |  |  |  | traits => [qw(ChainedClone)] | 
| 26 |  |  |  |  |  |  | ); | 
| 27 |  |  |  |  |  |  |  | 
| 28 |  |  |  |  |  |  | has filter => ( | 
| 29 |  |  |  |  |  |  | isa    => 'HashRef', | 
| 30 |  |  |  |  |  |  | is     => 'rw', | 
| 31 |  |  |  |  |  |  | traits => [qw(ChainedClone)] | 
| 32 |  |  |  |  |  |  | ); | 
| 33 |  |  |  |  |  |  |  | 
| 34 |  |  |  |  |  |  | has [qw(from size)] => | 
| 35 |  |  |  |  |  |  | ( isa => 'Int', is => 'rw', traits => [qw(ChainedClone)] ); | 
| 36 |  |  |  |  |  |  |  | 
| 37 |  |  |  |  |  |  | has [qw(fields sort)] => ( | 
| 38 |  |  |  |  |  |  | isa    => 'ArrayRef', | 
| 39 |  |  |  |  |  |  | is     => 'rw', | 
| 40 |  |  |  |  |  |  | traits => [qw(ChainedClone)] | 
| 41 |  |  |  |  |  |  | ); | 
| 42 |  |  |  |  |  |  |  | 
| 43 |  |  |  |  |  |  | has source => ( | 
| 44 |  |  |  |  |  |  | is      => 'rw', | 
| 45 |  |  |  |  |  |  | traits  => [qw(ChainedClone)], | 
| 46 |  |  |  |  |  |  | default => sub { \1 }, | 
| 47 |  |  |  |  |  |  | ); | 
| 48 |  |  |  |  |  |  |  | 
| 49 | 0 |  |  | 0 | 0 | 0 | sub add_sort { push( @{ $_[0]->sort }, $_[1] ); return $_[0]; } | 
|  | 0 |  |  |  |  | 0 |  | 
|  | 0 |  |  |  |  | 0 |  | 
| 50 |  |  |  |  |  |  |  | 
| 51 | 0 |  |  | 0 | 0 | 0 | sub add_field { push( @{ $_[0]->fields }, $_[1] ); return $_[0]; } | 
|  | 0 |  |  |  |  | 0 |  | 
|  | 0 |  |  |  |  | 0 |  | 
| 52 |  |  |  |  |  |  |  | 
| 53 |  |  |  |  |  |  | has search_type => | 
| 54 |  |  |  |  |  |  | ( isa => QueryType, is => 'rw', traits => [qw(ChainedClone)] ); | 
| 55 |  |  |  |  |  |  |  | 
| 56 | 0 |  |  | 0 | 0 | 0 | sub query_type { shift->search_type(@_) } | 
| 57 |  |  |  |  |  |  |  | 
| 58 |  |  |  |  |  |  | has mixin => ( is => 'ro', isa => 'HashRef', traits => [qw(ChainedClone)] ); | 
| 59 |  |  |  |  |  |  |  | 
| 60 |  |  |  |  |  |  | has inflate => | 
| 61 |  |  |  |  |  |  | ( isa => 'Bool', default => 1, is => 'rw', traits => [qw(ChainedClone)] ); | 
| 62 |  |  |  |  |  |  |  | 
| 63 |  |  |  |  |  |  | sub raw { | 
| 64 | 0 |  |  | 0 | 1 | 0 | shift->inflate(0); | 
| 65 |  |  |  |  |  |  | } | 
| 66 |  |  |  |  |  |  |  | 
| 67 |  |  |  |  |  |  | has _refresh => | 
| 68 |  |  |  |  |  |  | ( isa => 'Bool', default => 0, is => 'rw', traits => [qw(ChainedClone)] ); | 
| 69 |  |  |  |  |  |  |  | 
| 70 |  |  |  |  |  |  | sub refresh { | 
| 71 | 0 |  |  | 0 | 1 | 0 | shift->_refresh(1); | 
| 72 |  |  |  |  |  |  | } | 
| 73 |  |  |  |  |  |  |  | 
| 74 |  |  |  |  |  |  | sub _build_qs { | 
| 75 | 0 |  |  | 0 |  | 0 | my ( $self, $qs ) = @_; | 
| 76 | 0 |  | 0 |  |  | 0 | $qs ||= {}; | 
| 77 |  |  |  |  |  |  |  | 
| 78 |  |  |  |  |  |  | # we only want to set qs if they are not the default | 
| 79 | 0 | 0 |  |  |  | 0 | $qs->{refresh} = 1 if ( $self->_refresh ); | 
| 80 | 0 | 0 |  |  |  | 0 | $qs->{search_type} = $self->search_type if $self->search_type; | 
| 81 | 0 |  |  |  |  | 0 | return $qs; | 
| 82 |  |  |  |  |  |  | } | 
| 83 |  |  |  |  |  |  |  | 
| 84 |  |  |  |  |  |  | sub _build_query { | 
| 85 | 0 |  |  | 0 |  | 0 | my $self = shift; | 
| 86 | 0 |  | 0 |  |  | 0 | my $q = $self->query || { match_all => {} }; | 
| 87 | 0 | 0 |  |  |  | 0 | if ( my $f = $self->filter ) { | 
| 88 | 0 |  |  |  |  | 0 | $q = { filtered => { query => $q, filter => $f } }; | 
| 89 |  |  |  |  |  |  | } | 
| 90 |  |  |  |  |  |  | return { | 
| 91 |  |  |  |  |  |  | query   => $q, | 
| 92 |  |  |  |  |  |  | _source => $self->source, | 
| 93 |  |  |  |  |  |  | $self->size   ? ( size   => $self->size )   : (), | 
| 94 |  |  |  |  |  |  | $self->from   ? ( from   => $self->from )   : (), | 
| 95 |  |  |  |  |  |  | $self->fields ? ( fields => $self->fields ) : (), | 
| 96 |  |  |  |  |  |  | $self->sort   ? ( sort   => $self->sort )   : (), | 
| 97 | 0 | 0 |  |  |  | 0 | $self->mixin ? ( %{ $self->mixin } ) : (), | 
|  | 0 | 0 |  |  |  | 0 |  | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
|  |  | 0 |  |  |  |  |  | 
| 98 |  |  |  |  |  |  | }; | 
| 99 |  |  |  |  |  |  | } | 
| 100 |  |  |  |  |  |  |  | 
| 101 |  |  |  |  |  |  | sub put { | 
| 102 | 0 |  |  | 0 | 1 | 0 | my ( $self, $args, $qs ) = @_; | 
| 103 | 0 |  |  |  |  | 0 | my $doc = $self->new_document($args); | 
| 104 | 0 |  |  |  |  | 0 | $doc->put( $self->_build_qs($qs) ); | 
| 105 | 0 |  |  |  |  | 0 | return $doc; | 
| 106 |  |  |  |  |  |  | } | 
| 107 |  |  |  |  |  |  |  | 
| 108 |  |  |  |  |  |  | sub new_document { | 
| 109 | 1 |  |  | 1 | 1 | 2 | my ( $self, $args ) = @_; | 
| 110 | 1 |  |  |  |  | 34 | return $self->type->name->new( %$args, index => $self->index ); | 
| 111 |  |  |  |  |  |  | } | 
| 112 |  |  |  |  |  |  |  | 
| 113 |  |  |  |  |  |  | sub inflate_result { | 
| 114 | 0 |  |  | 0 | 0 |  | my ( $self, $res ) = @_; | 
| 115 | 0 |  |  |  |  |  | my ( $type, $index ) = ( $res->{_type}, $res->{_index} ); | 
| 116 | 0 | 0 |  |  |  |  | $index = $index ? $self->model->index($index) : $self->index; | 
| 117 | 0 | 0 |  |  |  |  | $type  = $type  ? $index->get_type($type)     : $self->type; | 
| 118 | 0 |  |  |  |  |  | my $doc = $type->inflate_result( $index, $res ); | 
| 119 | 0 | 0 |  |  |  |  | unless ( $res->{_source} ) { | 
| 120 | 0 |  |  |  |  |  | $doc->_loaded_attributes( { map { $_ => 1 } @{ $self->fields } } ); | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
| 121 |  |  |  |  |  |  | } | 
| 122 | 0 |  |  |  |  |  | return $doc; | 
| 123 |  |  |  |  |  |  | } | 
| 124 |  |  |  |  |  |  |  | 
| 125 |  |  |  |  |  |  | sub get { | 
| 126 | 0 |  |  | 0 | 1 |  | my ( $self, $args, $qs ) = @_; | 
| 127 | 0 |  |  |  |  |  | $qs = $self->_build_qs($qs); | 
| 128 | 0 |  |  |  |  |  | my ($id); | 
| 129 | 0 |  |  |  |  |  | my ( $index, $type ) = ( $self->index->name, $self->type->short_name ); | 
| 130 |  |  |  |  |  |  |  | 
| 131 | 0 | 0 |  |  |  |  | if ( !ref $args ) { | 
|  |  | 0 |  |  |  |  |  | 
| 132 | 0 |  |  |  |  |  | $id = $args; | 
| 133 |  |  |  |  |  |  | } | 
| 134 |  |  |  |  |  |  | elsif ( my $pk = $self->type->get_id_attribute ) { | 
| 135 | 0 |  |  |  |  |  | my $found = 0; | 
| 136 |  |  |  |  |  |  | my @fields | 
| 137 | 0 |  |  |  |  |  | = map { $self->type->find_attribute_by_name($_) } @{ $pk->id }; | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
| 138 | 0 |  |  |  |  |  | map { $found++ } grep { exists $args->{ $_->name } } @fields; | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
| 139 | 0 | 0 |  |  |  |  | die "All id fields need to be supplied to get: @fields" | 
| 140 |  |  |  |  |  |  | unless ( @fields == $found ); | 
| 141 |  |  |  |  |  |  | $id = ElasticSearchX::Model::Util::digest( | 
| 142 |  |  |  |  |  |  | map { | 
| 143 | 0 |  |  |  |  |  | $_->has_deflator | 
| 144 |  |  |  |  |  |  | ? $_->deflate( $self, $args->{ $_->name } ) | 
| 145 | 0 | 0 |  |  |  |  | : $args->{ $_->name } | 
| 146 |  |  |  |  |  |  | } @fields | 
| 147 |  |  |  |  |  |  | ); | 
| 148 |  |  |  |  |  |  | } | 
| 149 |  |  |  |  |  |  |  | 
| 150 |  |  |  |  |  |  | my $res = $self->es->get( | 
| 151 |  |  |  |  |  |  | index => $index, | 
| 152 |  |  |  |  |  |  | type  => $type, | 
| 153 |  |  |  |  |  |  | id    => $id, | 
| 154 |  |  |  |  |  |  | $self->fields ? ( fields => $self->fields ) : (), | 
| 155 |  |  |  |  |  |  | ignore => [404], | 
| 156 | 0 | 0 |  |  |  |  | %{ $qs || {} }, | 
|  | 0 | 0 |  |  |  |  |  | 
| 157 |  |  |  |  |  |  | ); | 
| 158 | 0 | 0 |  |  |  |  | return undef unless ($res); | 
| 159 | 0 | 0 |  |  |  |  | return $self->inflate ? $self->inflate_result($res) : $res; | 
| 160 |  |  |  |  |  |  | } | 
| 161 |  |  |  |  |  |  |  | 
| 162 |  |  |  |  |  |  | sub all { | 
| 163 | 0 |  |  | 0 | 1 |  | my ( $self, $qs ) = @_; | 
| 164 | 0 |  |  |  |  |  | $qs = $self->_build_qs($qs); | 
| 165 | 0 |  |  |  |  |  | my ( $index, $type ) = ( $self->index->name, $self->type->short_name ); | 
| 166 |  |  |  |  |  |  | my $res = $self->es->search( | 
| 167 |  |  |  |  |  |  | { | 
| 168 |  |  |  |  |  |  | index   => $index, | 
| 169 |  |  |  |  |  |  | type    => $type, | 
| 170 |  |  |  |  |  |  | body    => $self->_build_query, | 
| 171 |  |  |  |  |  |  | version => 1, | 
| 172 | 0 | 0 |  |  |  |  | %{ $qs || {} }, | 
|  | 0 |  |  |  |  |  |  | 
| 173 |  |  |  |  |  |  | } | 
| 174 |  |  |  |  |  |  | ); | 
| 175 | 0 | 0 |  |  |  |  | return $res unless ( $self->inflate ); | 
| 176 | 0 | 0 |  |  |  |  | return ()   unless ( $res->{hits}->{total} ); | 
| 177 | 0 |  |  |  |  |  | return map { $self->inflate_result($_) } @{ $res->{hits}->{hits} }; | 
|  | 0 |  |  |  |  |  |  | 
|  | 0 |  |  |  |  |  |  | 
| 178 |  |  |  |  |  |  | } | 
| 179 |  |  |  |  |  |  |  | 
| 180 |  |  |  |  |  |  | sub first { | 
| 181 | 0 |  |  | 0 | 1 |  | my ( $self, $qs ) = @_; | 
| 182 | 0 |  |  |  |  |  | $qs = $self->_build_qs($qs); | 
| 183 | 0 |  |  |  |  |  | my @data = $self->size(1)->all($qs); | 
| 184 | 0 | 0 |  |  |  |  | return undef unless (@data); | 
| 185 | 0 | 0 |  |  |  |  | return $data[0] if ( $self->inflate ); | 
| 186 | 0 |  |  |  |  |  | return $data[0]->{hits}->{hits}->[0]; | 
| 187 |  |  |  |  |  |  | } | 
| 188 |  |  |  |  |  |  |  | 
| 189 |  |  |  |  |  |  | sub count { | 
| 190 | 0 |  |  | 0 | 1 |  | my ( $self, $qs ) = @_; | 
| 191 | 0 |  |  |  |  |  | $qs = $self->_build_qs($qs); | 
| 192 | 0 |  |  |  |  |  | my ( $index, $type ) = ( $self->index->name, $self->type->short_name ); | 
| 193 | 0 |  |  |  |  |  | my $query = $self->_build_query; | 
| 194 | 0 |  |  |  |  |  | delete $query->{_source}; | 
| 195 | 0 |  |  |  |  |  | my $res = $self->es->count( | 
| 196 |  |  |  |  |  |  | { | 
| 197 |  |  |  |  |  |  | index => $index, | 
| 198 |  |  |  |  |  |  | type  => $type, | 
| 199 |  |  |  |  |  |  | body  => $query, | 
| 200 |  |  |  |  |  |  | %$qs, | 
| 201 |  |  |  |  |  |  | } | 
| 202 |  |  |  |  |  |  | ); | 
| 203 | 0 |  |  |  |  |  | return $res->{count}; | 
| 204 |  |  |  |  |  |  | } | 
| 205 |  |  |  |  |  |  |  | 
| 206 |  |  |  |  |  |  | sub delete { | 
| 207 | 0 |  |  | 0 | 1 |  | my ( $self, $qs ) = @_; | 
| 208 | 0 |  |  |  |  |  | $qs = $self->_build_qs($qs); | 
| 209 | 0 |  |  |  |  |  | my $query = $self->_build_query; | 
| 210 | 0 |  |  |  |  |  | delete $query->{_source}; | 
| 211 |  |  |  |  |  |  |  | 
| 212 | 0 |  |  |  |  |  | my %idx_type = ( | 
| 213 |  |  |  |  |  |  | index => $self->index->name, | 
| 214 |  |  |  |  |  |  | type  => $self->type->short_name | 
| 215 |  |  |  |  |  |  | ); | 
| 216 |  |  |  |  |  |  |  | 
| 217 | 0 |  |  |  |  |  | my $sc = $self->es->scroll_helper( | 
| 218 |  |  |  |  |  |  | search_type => 'scan', | 
| 219 |  |  |  |  |  |  | body        => $self->_build_query, | 
| 220 |  |  |  |  |  |  | size        => 500, | 
| 221 |  |  |  |  |  |  | %idx_type, | 
| 222 |  |  |  |  |  |  | %$qs, | 
| 223 |  |  |  |  |  |  | ); | 
| 224 |  |  |  |  |  |  |  | 
| 225 | 0 |  |  |  |  |  | my @ids; | 
| 226 | 0 |  |  |  |  |  | while ( my @d = $sc->next(500) ) { | 
| 227 | 0 |  |  |  |  |  | push @ids => map { $_->{_id} } @d; | 
|  | 0 |  |  |  |  |  |  | 
| 228 |  |  |  |  |  |  | } | 
| 229 |  |  |  |  |  |  |  | 
| 230 | 0 |  |  |  |  |  | my $bulk = $self->es->bulk_helper(%idx_type); | 
| 231 | 0 |  |  |  |  |  | $bulk->delete_ids(@ids); | 
| 232 | 0 |  |  |  |  |  | return $bulk->flush; | 
| 233 |  |  |  |  |  |  | } | 
| 234 |  |  |  |  |  |  |  | 
| 235 |  |  |  |  |  |  | sub scroll { | 
| 236 | 0 |  |  | 0 | 1 |  | my ( $self, $scroll, $qs ) = @_; | 
| 237 |  |  |  |  |  |  | return ElasticSearchX::Model::Scroll->new( | 
| 238 |  |  |  |  |  |  | set => $self, | 
| 239 |  |  |  |  |  |  | scroll => $scroll || '1m', | 
| 240 | 0 | 0 | 0 |  |  |  | qs => $self->_build_qs( { version => 1, %{ $qs || {} } } ), | 
|  | 0 |  |  |  |  |  |  | 
| 241 |  |  |  |  |  |  | ); | 
| 242 |  |  |  |  |  |  | } | 
| 243 |  |  |  |  |  |  |  | 
| 244 |  |  |  |  |  |  | __PACKAGE__->meta->make_immutable; | 
| 245 |  |  |  |  |  |  |  | 
| 246 |  |  |  |  |  |  | __END__ | 
| 247 |  |  |  |  |  |  |  | 
| 248 |  |  |  |  |  |  | =pod | 
| 249 |  |  |  |  |  |  |  | 
| 250 |  |  |  |  |  |  | =encoding UTF-8 | 
| 251 |  |  |  |  |  |  |  | 
| 252 |  |  |  |  |  |  | =head1 NAME | 
| 253 |  |  |  |  |  |  |  | 
| 254 |  |  |  |  |  |  | ElasticSearchX::Model::Document::Set - Represents a query used for fetching a set of results | 
| 255 |  |  |  |  |  |  |  | 
| 256 |  |  |  |  |  |  | =head1 VERSION | 
| 257 |  |  |  |  |  |  |  | 
| 258 |  |  |  |  |  |  | version 1.0.2 | 
| 259 |  |  |  |  |  |  |  | 
| 260 |  |  |  |  |  |  | =head1 SYNOPSIS | 
| 261 |  |  |  |  |  |  |  | 
| 262 |  |  |  |  |  |  | my $type = $model->index('default')->type('tweet'); | 
| 263 |  |  |  |  |  |  | my $all  = $type->all; | 
| 264 |  |  |  |  |  |  |  | 
| 265 |  |  |  |  |  |  | my $result = $type->filter( { term => { message => 'hello' } } )->first; | 
| 266 |  |  |  |  |  |  |  | 
| 267 |  |  |  |  |  |  | my $tweet | 
| 268 |  |  |  |  |  |  | = $type->get( { user => 'mo', post_date => DateTime->now->iso8601 } ); | 
| 269 |  |  |  |  |  |  |  | 
| 270 |  |  |  |  |  |  |  | 
| 271 |  |  |  |  |  |  | package MyModel::Tweet::Set; | 
| 272 |  |  |  |  |  |  |  | 
| 273 |  |  |  |  |  |  | use Moose; | 
| 274 |  |  |  |  |  |  | extends 'ElasticSearchX::Model::Document::Set'; | 
| 275 |  |  |  |  |  |  |  | 
| 276 |  |  |  |  |  |  | sub hello { | 
| 277 |  |  |  |  |  |  | my $self = shift; | 
| 278 |  |  |  |  |  |  | return $self->filter({ | 
| 279 |  |  |  |  |  |  | term => { message => 'hello' } | 
| 280 |  |  |  |  |  |  | }); | 
| 281 |  |  |  |  |  |  | } | 
| 282 |  |  |  |  |  |  |  | 
| 283 |  |  |  |  |  |  | __PACKAGE__->meta->make_immutable; | 
| 284 |  |  |  |  |  |  |  | 
| 285 |  |  |  |  |  |  | my $result = $type->hello->first; | 
| 286 |  |  |  |  |  |  |  | 
| 287 |  |  |  |  |  |  | =head1 DESCRIPTION | 
| 288 |  |  |  |  |  |  |  | 
| 289 |  |  |  |  |  |  | Whenever a type is accessed by calling L<ElasticSearchX::Model::Index/type> | 
| 290 |  |  |  |  |  |  | you will receive an instance of this class.  The instance can then be used | 
| 291 |  |  |  |  |  |  | to build new objects (L</new_document>), put new documents in the index | 
| 292 |  |  |  |  |  |  | (L</put>), do search and so on. | 
| 293 |  |  |  |  |  |  |  | 
| 294 |  |  |  |  |  |  | =head1 SUBCLASSING | 
| 295 |  |  |  |  |  |  |  | 
| 296 |  |  |  |  |  |  | If you define a C<::Set> class on top of your document class, this class | 
| 297 |  |  |  |  |  |  | will be used as set class. This allows you to put most of your business | 
| 298 |  |  |  |  |  |  | logic in this class. | 
| 299 |  |  |  |  |  |  |  | 
| 300 |  |  |  |  |  |  | =head1 ATTRIBUTES | 
| 301 |  |  |  |  |  |  |  | 
| 302 |  |  |  |  |  |  | All attributes have the L<MooseX::Attribute::ChainedClone> trait applied. | 
| 303 |  |  |  |  |  |  | That means that you can chain calls to these attributes and that a cloned | 
| 304 |  |  |  |  |  |  | instance is returned whenever you set an attribute. This pattern is inspired | 
| 305 |  |  |  |  |  |  | by L<DBIx::Class::ResultSet/search>. | 
| 306 |  |  |  |  |  |  |  | 
| 307 |  |  |  |  |  |  | my $type = $model->index('default')->type('tweet'); | 
| 308 |  |  |  |  |  |  | my @documents = $type->fields(['user'])->all; | 
| 309 |  |  |  |  |  |  | # $type->fields has not been touched, instead a cloned instance of $type | 
| 310 |  |  |  |  |  |  | # has been created with "fields" set to ['user'] | 
| 311 |  |  |  |  |  |  |  | 
| 312 |  |  |  |  |  |  | $type = $type->fields(['user']); | 
| 313 |  |  |  |  |  |  | # this will set $type to a cloned instance of $type with fields | 
| 314 |  |  |  |  |  |  | # set to ['user'] | 
| 315 |  |  |  |  |  |  | @documents = $type->all; | 
| 316 |  |  |  |  |  |  | # same result as above | 
| 317 |  |  |  |  |  |  |  | 
| 318 |  |  |  |  |  |  | =head2 filter | 
| 319 |  |  |  |  |  |  |  | 
| 320 |  |  |  |  |  |  | Adds a filter to the query. If no L</query> is given, it will automatically | 
| 321 |  |  |  |  |  |  | build a C<filtered> query, which performs far better. | 
| 322 |  |  |  |  |  |  |  | 
| 323 |  |  |  |  |  |  | =head2 query | 
| 324 |  |  |  |  |  |  |  | 
| 325 |  |  |  |  |  |  | =head2 size | 
| 326 |  |  |  |  |  |  |  | 
| 327 |  |  |  |  |  |  | =head2 from | 
| 328 |  |  |  |  |  |  |  | 
| 329 |  |  |  |  |  |  | =head2 fields | 
| 330 |  |  |  |  |  |  |  | 
| 331 |  |  |  |  |  |  | =head2 sort | 
| 332 |  |  |  |  |  |  |  | 
| 333 |  |  |  |  |  |  | =head2 search_type | 
| 334 |  |  |  |  |  |  |  | 
| 335 |  |  |  |  |  |  | These attributes are passed directly to the ElasticSearch search request. | 
| 336 |  |  |  |  |  |  |  | 
| 337 |  |  |  |  |  |  | =head2 mixin | 
| 338 |  |  |  |  |  |  |  | 
| 339 |  |  |  |  |  |  | The previously mentioned attributes don't cover all of | 
| 340 |  |  |  |  |  |  | ElasticSearch's options for searching. You can set the | 
| 341 |  |  |  |  |  |  | L</mixin> attribute to a HashRef which is then merged with | 
| 342 |  |  |  |  |  |  | the attributes. | 
| 343 |  |  |  |  |  |  |  | 
| 344 |  |  |  |  |  |  | =head2 inflate | 
| 345 |  |  |  |  |  |  |  | 
| 346 |  |  |  |  |  |  | Inflate the returned results to the appropriate document | 
| 347 |  |  |  |  |  |  | object. Defaults to C<1>. You can either use C<< $type->inflate(0) >> | 
| 348 |  |  |  |  |  |  | to disable this behaviour for extra speed, or you can | 
| 349 |  |  |  |  |  |  | use the L</raw> convenience method. | 
| 350 |  |  |  |  |  |  |  | 
| 351 |  |  |  |  |  |  | =head2 index | 
| 352 |  |  |  |  |  |  |  | 
| 353 |  |  |  |  |  |  | =head2 type | 
| 354 |  |  |  |  |  |  |  | 
| 355 |  |  |  |  |  |  | =head1 METHODS | 
| 356 |  |  |  |  |  |  |  | 
| 357 |  |  |  |  |  |  | =head2 all | 
| 358 |  |  |  |  |  |  |  | 
| 359 |  |  |  |  |  |  | =head2 all( { %qs } ) | 
| 360 |  |  |  |  |  |  |  | 
| 361 |  |  |  |  |  |  | Returns all results as a list, limited by L</size> and L</from>. | 
| 362 |  |  |  |  |  |  |  | 
| 363 |  |  |  |  |  |  | =head2 scroll | 
| 364 |  |  |  |  |  |  |  | 
| 365 |  |  |  |  |  |  | =head2 scroll( $scroll, { %qs } ) | 
| 366 |  |  |  |  |  |  |  | 
| 367 |  |  |  |  |  |  | my $iterator = $twitter->type('tweet')->scroll; | 
| 368 |  |  |  |  |  |  | while ( my $tweet = $iterator->next ) { | 
| 369 |  |  |  |  |  |  | # do something | 
| 370 |  |  |  |  |  |  | } | 
| 371 |  |  |  |  |  |  |  | 
| 372 |  |  |  |  |  |  | Large results should be scrolled thorugh using this iterator. | 
| 373 |  |  |  |  |  |  | It will return an instance of L<ElasticSearchX::Model::Scroll>. | 
| 374 |  |  |  |  |  |  | The C<$scroll> parameter is a time value parameter (for example: C<5m>), | 
| 375 |  |  |  |  |  |  | indicating for how long the nodes that participate in the search will | 
| 376 |  |  |  |  |  |  | maintain relevant resources in order to continue and support it. | 
| 377 |  |  |  |  |  |  | C<$scroll> defaults to C<1m>. | 
| 378 |  |  |  |  |  |  |  | 
| 379 |  |  |  |  |  |  | Scrolling is executed by pulling in L</size> number of documents. | 
| 380 |  |  |  |  |  |  |  | 
| 381 |  |  |  |  |  |  | =head2 first | 
| 382 |  |  |  |  |  |  |  | 
| 383 |  |  |  |  |  |  | =head2 first( { %qs } ) | 
| 384 |  |  |  |  |  |  |  | 
| 385 |  |  |  |  |  |  | Returns the first result only. It automatically sets | 
| 386 |  |  |  |  |  |  | L</size> to C<1> to speed up the retrieval. However, | 
| 387 |  |  |  |  |  |  | it doesn't touch L</from>. In order to get the second | 
| 388 |  |  |  |  |  |  | result, you would do: | 
| 389 |  |  |  |  |  |  |  | 
| 390 |  |  |  |  |  |  | my $second = $type->from(2)->first; | 
| 391 |  |  |  |  |  |  |  | 
| 392 |  |  |  |  |  |  | =head2 count | 
| 393 |  |  |  |  |  |  |  | 
| 394 |  |  |  |  |  |  | Returns the number of results. | 
| 395 |  |  |  |  |  |  |  | 
| 396 |  |  |  |  |  |  | =head2 delete | 
| 397 |  |  |  |  |  |  |  | 
| 398 |  |  |  |  |  |  | =head2 delete( { %qs } ) | 
| 399 |  |  |  |  |  |  |  | 
| 400 |  |  |  |  |  |  | Delete all documents that match the query. Issues a call to | 
| 401 |  |  |  |  |  |  | L<ElasticSearch/delete_by_query()>. | 
| 402 |  |  |  |  |  |  |  | 
| 403 |  |  |  |  |  |  | =head2 get | 
| 404 |  |  |  |  |  |  |  | 
| 405 |  |  |  |  |  |  | =head2 get( { %qs } ) | 
| 406 |  |  |  |  |  |  |  | 
| 407 |  |  |  |  |  |  | $type->get('fd_ZGWupT2KOxw3w9Q7VSA'); | 
| 408 |  |  |  |  |  |  |  | 
| 409 |  |  |  |  |  |  | $type->get({ | 
| 410 |  |  |  |  |  |  | user => 'mo', | 
| 411 |  |  |  |  |  |  | post_date => $dt->iso8601, | 
| 412 |  |  |  |  |  |  | }); | 
| 413 |  |  |  |  |  |  |  | 
| 414 |  |  |  |  |  |  | Get a document by its id from ElasticSearch. You can either | 
| 415 |  |  |  |  |  |  | pass the id as a string or you can pass a HashRef of | 
| 416 |  |  |  |  |  |  | the values that make up the id. | 
| 417 |  |  |  |  |  |  |  | 
| 418 |  |  |  |  |  |  | =head2 put | 
| 419 |  |  |  |  |  |  |  | 
| 420 |  |  |  |  |  |  | =head2 put( { %qs } ) | 
| 421 |  |  |  |  |  |  |  | 
| 422 |  |  |  |  |  |  | my $doc = $type->put({ | 
| 423 |  |  |  |  |  |  | message => 'hello', | 
| 424 |  |  |  |  |  |  | }); | 
| 425 |  |  |  |  |  |  |  | 
| 426 |  |  |  |  |  |  | This methods builds a new document using L</new_document> and | 
| 427 |  |  |  |  |  |  | pushes it to the index. It returns the created document. If | 
| 428 |  |  |  |  |  |  | no id was supplied, the id will be fetched from ElasticSearch | 
| 429 |  |  |  |  |  |  | and set on the object in the C<_id> attribute. | 
| 430 |  |  |  |  |  |  |  | 
| 431 |  |  |  |  |  |  | =head2 new_document | 
| 432 |  |  |  |  |  |  |  | 
| 433 |  |  |  |  |  |  | my $doc = $type->new_document({ | 
| 434 |  |  |  |  |  |  | message => 'hello', | 
| 435 |  |  |  |  |  |  | }); | 
| 436 |  |  |  |  |  |  |  | 
| 437 |  |  |  |  |  |  | Builds a new document but doesn't commit it just yet. You | 
| 438 |  |  |  |  |  |  | can manually commit the new document by calling | 
| 439 |  |  |  |  |  |  | L<ElasticSearchX::Model::Document/put> on the document | 
| 440 |  |  |  |  |  |  | object. | 
| 441 |  |  |  |  |  |  |  | 
| 442 |  |  |  |  |  |  | =head2 raw | 
| 443 |  |  |  |  |  |  |  | 
| 444 |  |  |  |  |  |  | Don't inflate returned results. This is a convenience | 
| 445 |  |  |  |  |  |  | method around L</inflate>. | 
| 446 |  |  |  |  |  |  |  | 
| 447 |  |  |  |  |  |  | =head2 refresh | 
| 448 |  |  |  |  |  |  |  | 
| 449 |  |  |  |  |  |  | This will add the C<refresh> query parameter to all requests. | 
| 450 |  |  |  |  |  |  |  | 
| 451 |  |  |  |  |  |  | $users->refresh->put( { nickname => 'mo' } ); | 
| 452 |  |  |  |  |  |  |  | 
| 453 |  |  |  |  |  |  | =head1 AUTHOR | 
| 454 |  |  |  |  |  |  |  | 
| 455 |  |  |  |  |  |  | Moritz Onken | 
| 456 |  |  |  |  |  |  |  | 
| 457 |  |  |  |  |  |  | =head1 COPYRIGHT AND LICENSE | 
| 458 |  |  |  |  |  |  |  | 
| 459 |  |  |  |  |  |  | This software is Copyright (c) 2016 by Moritz Onken. | 
| 460 |  |  |  |  |  |  |  | 
| 461 |  |  |  |  |  |  | This is free software, licensed under: | 
| 462 |  |  |  |  |  |  |  | 
| 463 |  |  |  |  |  |  | The (three-clause) BSD License | 
| 464 |  |  |  |  |  |  |  | 
| 465 |  |  |  |  |  |  | =cut |