elastictastic 0.5.0 → 0.10.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/LICENSE +1 -1
 - data/README.md +161 -10
 - data/lib/elastictastic/adapter.rb +84 -0
 - data/lib/elastictastic/association.rb +6 -0
 - data/lib/elastictastic/basic_document.rb +213 -0
 - data/lib/elastictastic/bulk_persistence_strategy.rb +64 -19
 - data/lib/elastictastic/callbacks.rb +18 -12
 - data/lib/elastictastic/child_collection_proxy.rb +15 -11
 - data/lib/elastictastic/client.rb +47 -24
 - data/lib/elastictastic/configuration.rb +59 -4
 - data/lib/elastictastic/dirty.rb +43 -28
 - data/lib/elastictastic/discrete_persistence_strategy.rb +48 -23
 - data/lib/elastictastic/document.rb +1 -85
 - data/lib/elastictastic/embedded_document.rb +34 -0
 - data/lib/elastictastic/errors.rb +17 -5
 - data/lib/elastictastic/field.rb +3 -0
 - data/lib/elastictastic/mass_assignment_security.rb +2 -4
 - data/lib/elastictastic/middleware.rb +66 -84
 - data/lib/elastictastic/multi_get.rb +30 -0
 - data/lib/elastictastic/multi_search.rb +70 -0
 - data/lib/elastictastic/nested_document.rb +3 -27
 - data/lib/elastictastic/new_relic_instrumentation.rb +8 -8
 - data/lib/elastictastic/observing.rb +8 -6
 - data/lib/elastictastic/optimistic_locking.rb +57 -0
 - data/lib/elastictastic/parent_child.rb +56 -54
 - data/lib/elastictastic/persistence.rb +16 -16
 - data/lib/elastictastic/properties.rb +136 -96
 - data/lib/elastictastic/railtie.rb +1 -1
 - data/lib/elastictastic/rotor.rb +105 -0
 - data/lib/elastictastic/scope.rb +186 -56
 - data/lib/elastictastic/server_error.rb +20 -1
 - data/lib/elastictastic/test_helpers.rb +152 -97
 - data/lib/elastictastic/thrift/constants.rb +12 -0
 - data/lib/elastictastic/thrift/rest.rb +83 -0
 - data/lib/elastictastic/thrift/types.rb +124 -0
 - data/lib/elastictastic/thrift_adapter.rb +61 -0
 - data/lib/elastictastic/transport_methods.rb +27 -0
 - data/lib/elastictastic/validations.rb +11 -13
 - data/lib/elastictastic/version.rb +1 -1
 - data/lib/elastictastic.rb +148 -27
 - data/spec/environment.rb +1 -1
 - data/spec/examples/bulk_persistence_strategy_spec.rb +151 -23
 - data/spec/examples/callbacks_spec.rb +65 -34
 - data/spec/examples/dirty_spec.rb +160 -1
 - data/spec/examples/document_spec.rb +168 -106
 - data/spec/examples/middleware_spec.rb +1 -61
 - data/spec/examples/multi_get_spec.rb +127 -0
 - data/spec/examples/multi_search_spec.rb +113 -0
 - data/spec/examples/observing_spec.rb +24 -3
 - data/spec/examples/optimistic_locking_spec.rb +417 -0
 - data/spec/examples/parent_child_spec.rb +73 -33
 - data/spec/examples/properties_spec.rb +53 -0
 - data/spec/examples/rotor_spec.rb +132 -0
 - data/spec/examples/scope_spec.rb +78 -18
 - data/spec/examples/search_spec.rb +26 -0
 - data/spec/examples/validation_spec.rb +7 -1
 - data/spec/models/author.rb +1 -1
 - data/spec/models/blog.rb +2 -0
 - data/spec/models/comment.rb +1 -1
 - data/spec/models/photo.rb +9 -0
 - data/spec/models/post.rb +3 -0
 - metadata +97 -78
 - data/lib/elastictastic/resource.rb +0 -4
 - data/spec/examples/active_model_lint_spec.rb +0 -20
 
    
        data/lib/elastictastic/scope.rb
    CHANGED
    
    | 
         @@ -1,12 +1,12 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            require 'hashie'
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'elastictastic/search'
         
     | 
| 
       2 
3 
     | 
    
         | 
| 
       3 
4 
     | 
    
         
             
            module Elastictastic
         
     | 
| 
       4 
5 
     | 
    
         
             
              class Scope < BasicObject
         
     | 
| 
       5 
6 
     | 
    
         
             
                attr_reader :clazz, :index
         
     | 
| 
       6 
7 
     | 
    
         | 
| 
       7 
     | 
    
         
            -
                def initialize(index, clazz, search = Search.new,  
     | 
| 
       8 
     | 
    
         
            -
                  @index, @clazz, @search, @ 
     | 
| 
       9 
     | 
    
         
            -
                    index, clazz, search, parent_collection
         
     | 
| 
      
 8 
     | 
    
         
            +
                def initialize(index, clazz, search = Search.new, parent = nil, routing = nil)
         
     | 
| 
      
 9 
     | 
    
         
            +
                  @index, @clazz, @search, @parent, @routing = index, clazz, search, parent, routing
         
     | 
| 
       10 
10 
     | 
    
         
             
                end
         
     | 
| 
       11 
11 
     | 
    
         | 
| 
       12 
12 
     | 
    
         
             
                def initialize_instance(instance)
         
     | 
| 
         @@ -26,6 +26,29 @@ module Elastictastic 
     | 
|
| 
       26 
26 
     | 
    
         
             
                  end
         
     | 
| 
       27 
27 
     | 
    
         
             
                end
         
     | 
| 
       28 
28 
     | 
    
         | 
| 
      
 29 
     | 
    
         
            +
                #
         
     | 
| 
      
 30 
     | 
    
         
            +
                # Iterate over all documents matching this scope. The underlying mechanism
         
     | 
| 
      
 31 
     | 
    
         
            +
                # used differs depending on the construction of this scope:
         
     | 
| 
      
 32 
     | 
    
         
            +
                #
         
     | 
| 
      
 33 
     | 
    
         
            +
                # * If the scope has a size, documents will be retrieved in a single request
         
     | 
| 
      
 34 
     | 
    
         
            +
                # * If the scope has a sort but no size, documents will be retrieved in
         
     | 
| 
      
 35 
     | 
    
         
            +
                #   batches using a `query_then_fetch` search. *In this case, it is
         
     | 
| 
      
 36 
     | 
    
         
            +
                #   impossible to guarantee a consistent result set if concurrent
         
     | 
| 
      
 37 
     | 
    
         
            +
                #   modification is occurring.*
         
     | 
| 
      
 38 
     | 
    
         
            +
                # * If the scope has neither a sort nor a size, documents will be retrieved
         
     | 
| 
      
 39 
     | 
    
         
            +
                #   in batches using a cursor (search type `scan`). In this case, the result
         
     | 
| 
      
 40 
     | 
    
         
            +
                #   set is guaranteed to be consistent even if concurrent modification
         
     | 
| 
      
 41 
     | 
    
         
            +
                #   occurs.
         
     | 
| 
      
 42 
     | 
    
         
            +
                #
         
     | 
| 
      
 43 
     | 
    
         
            +
                # @param (see #find_in_batches)
         
     | 
| 
      
 44 
     | 
    
         
            +
                # @option (see #find_in_batches)
         
     | 
| 
      
 45 
     | 
    
         
            +
                # @yield [document, hit] Each result is yielded to the block
         
     | 
| 
      
 46 
     | 
    
         
            +
                # @yieldparam [Document] document A materialized Document instance
         
     | 
| 
      
 47 
     | 
    
         
            +
                # @yieldparam [Hashie::Mash] hit The raw hit from ElasticSearch, wrapped in
         
     | 
| 
      
 48 
     | 
    
         
            +
                #   a Hashie::Mash. Useful for extracting metadata, e.g. highlighting
         
     | 
| 
      
 49 
     | 
    
         
            +
                # @return [Enumerator] An enumerator, if no block is passed
         
     | 
| 
      
 50 
     | 
    
         
            +
                # @see http://www.elasticsearch.org/guide/reference/api/search/search-type.html
         
     | 
| 
      
 51 
     | 
    
         
            +
                #
         
     | 
| 
       29 
52 
     | 
    
         
             
                def find_each(batch_options = {}, &block)
         
     | 
| 
       30 
53 
     | 
    
         
             
                  if block
         
     | 
| 
       31 
54 
     | 
    
         
             
                    find_in_batches(batch_options) { |batch| batch.each(&block) }
         
     | 
| 
         @@ -34,6 +57,20 @@ module Elastictastic 
     | 
|
| 
       34 
57 
     | 
    
         
             
                  end
         
     | 
| 
       35 
58 
     | 
    
         
             
                end
         
     | 
| 
       36 
59 
     | 
    
         | 
| 
      
 60 
     | 
    
         
            +
                #
         
     | 
| 
      
 61 
     | 
    
         
            +
                # Yield batches of documents matching this scope. See #find_each for a
         
     | 
| 
      
 62 
     | 
    
         
            +
                # discussion of different strategies for retrieving documents from
         
     | 
| 
      
 63 
     | 
    
         
            +
                # ElasticSearch depending on the construction of this scope.
         
     | 
| 
      
 64 
     | 
    
         
            +
                #
         
     | 
| 
      
 65 
     | 
    
         
            +
                # @option batch_options [Fixnum] :batch_size (Elastictastic.config.default_batch_size)
         
     | 
| 
      
 66 
     | 
    
         
            +
                #   How many documents to retrieve from the server in each batch.
         
     | 
| 
      
 67 
     | 
    
         
            +
                # @option batch_options [Fixnum] :ttl (60) How long to keep the cursor
         
     | 
| 
      
 68 
     | 
    
         
            +
                #   alive, in the case where search is performed with a cursor.
         
     | 
| 
      
 69 
     | 
    
         
            +
                # @yield [batch] Once for each batch of hits
         
     | 
| 
      
 70 
     | 
    
         
            +
                # @yieldparam [Enumerator] batch An enumerator for this batch of hits.
         
     | 
| 
      
 71 
     | 
    
         
            +
                #   The enumerator will yield a materialized Document and a Hashie::Mash wrapping each raw hit.
         
     | 
| 
      
 72 
     | 
    
         
            +
                # @return [Enumerator] An enumerator that yields batches, if no block is passed.
         
     | 
| 
      
 73 
     | 
    
         
            +
                #
         
     | 
| 
       37 
74 
     | 
    
         
             
                def find_in_batches(batch_options = {}, &block)
         
     | 
| 
       38 
75 
     | 
    
         
             
                  return ::Enumerator.new(self, :find_in_batches, batch_options) unless block
         
     | 
| 
       39 
76 
     | 
    
         
             
                  if params.key?('size') || params.key?('from')
         
     | 
| 
         @@ -73,6 +110,20 @@ module Elastictastic 
     | 
|
| 
       73 
110 
     | 
    
         
             
                  scoped({})
         
     | 
| 
       74 
111 
     | 
    
         
             
                end
         
     | 
| 
       75 
112 
     | 
    
         | 
| 
      
 113 
     | 
    
         
            +
                def [](index_or_range)
         
     | 
| 
      
 114 
     | 
    
         
            +
                  case index_or_range
         
     | 
| 
      
 115 
     | 
    
         
            +
                  when ::Integer
         
     | 
| 
      
 116 
     | 
    
         
            +
                    from(index_or_range).size(1).to_a.first
         
     | 
| 
      
 117 
     | 
    
         
            +
                  when ::Range
         
     | 
| 
      
 118 
     | 
    
         
            +
                    range_size = index_or_range.last - index_or_range.first
         
     | 
| 
      
 119 
     | 
    
         
            +
                    range_size += 1 unless index_or_range.exclude_end?
         
     | 
| 
      
 120 
     | 
    
         
            +
                    from(index_or_range.first).
         
     | 
| 
      
 121 
     | 
    
         
            +
                      size(range_size)
         
     | 
| 
      
 122 
     | 
    
         
            +
                  else
         
     | 
| 
      
 123 
     | 
    
         
            +
                    raise ::ArgumentError, "Expected Integer or Range"
         
     | 
| 
      
 124 
     | 
    
         
            +
                  end
         
     | 
| 
      
 125 
     | 
    
         
            +
                end
         
     | 
| 
      
 126 
     | 
    
         
            +
             
     | 
| 
       76 
127 
     | 
    
         
             
                def all_facets
         
     | 
| 
       77 
128 
     | 
    
         
             
                  return @all_facets if defined? @all_facets
         
     | 
| 
       78 
129 
     | 
    
         
             
                  populate_counts
         
     | 
| 
         @@ -84,10 +135,16 @@ module Elastictastic 
     | 
|
| 
       84 
135 
     | 
    
         
             
                    @index,
         
     | 
| 
       85 
136 
     | 
    
         
             
                    @clazz,
         
     | 
| 
       86 
137 
     | 
    
         
             
                    @search.merge(Search.new(params)),
         
     | 
| 
       87 
     | 
    
         
            -
                    @ 
     | 
| 
      
 138 
     | 
    
         
            +
                    @parent,
         
     | 
| 
      
 139 
     | 
    
         
            +
                    @routing
         
     | 
| 
       88 
140 
     | 
    
         
             
                  )
         
     | 
| 
       89 
141 
     | 
    
         
             
                end
         
     | 
| 
       90 
142 
     | 
    
         | 
| 
      
 143 
     | 
    
         
            +
                #
         
     | 
| 
      
 144 
     | 
    
         
            +
                # Destroy all documents in this index.
         
     | 
| 
      
 145 
     | 
    
         
            +
                #
         
     | 
| 
      
 146 
     | 
    
         
            +
                # @note This will *not* take into account filters or queries in this scope.
         
     | 
| 
      
 147 
     | 
    
         
            +
                #
         
     | 
| 
       91 
148 
     | 
    
         
             
                def destroy_all
         
     | 
| 
       92 
149 
     | 
    
         
             
                  #FIXME support delete-by-query
         
     | 
| 
       93 
150 
     | 
    
         
             
                  ::Elastictastic.client.delete(@index, @clazz.type)
         
     | 
| 
         @@ -98,13 +155,40 @@ module Elastictastic 
     | 
|
| 
       98 
155 
     | 
    
         
             
                  ::Elastictastic.client.put_mapping(index, type, @clazz.mapping)
         
     | 
| 
       99 
156 
     | 
    
         
             
                end
         
     | 
| 
       100 
157 
     | 
    
         | 
| 
      
 158 
     | 
    
         
            +
                def exists?(id)
         
     | 
| 
      
 159 
     | 
    
         
            +
                  ::Elastictastic.client.
         
     | 
| 
      
 160 
     | 
    
         
            +
                    exists?(index, type, id, params_for_find.slice('routing'))
         
     | 
| 
      
 161 
     | 
    
         
            +
                end
         
     | 
| 
      
 162 
     | 
    
         
            +
             
     | 
| 
      
 163 
     | 
    
         
            +
                #
         
     | 
| 
      
 164 
     | 
    
         
            +
                # Look up one or more documents by ID.
         
     | 
| 
      
 165 
     | 
    
         
            +
                #
         
     | 
| 
      
 166 
     | 
    
         
            +
                # Retrieve one or more Elastictastic documents by ID
         
     | 
| 
      
 167 
     | 
    
         
            +
                #
         
     | 
| 
      
 168 
     | 
    
         
            +
                # @overload find(*ids)
         
     | 
| 
      
 169 
     | 
    
         
            +
                #   Retrieve a single document or a collection of documents
         
     | 
| 
      
 170 
     | 
    
         
            +
                #
         
     | 
| 
      
 171 
     | 
    
         
            +
                #   @param [String] ids Document IDs
         
     | 
| 
      
 172 
     | 
    
         
            +
                #   @return [Elastictastic::BasicDocument,Array] Collection of documents with the given IDs
         
     | 
| 
      
 173 
     | 
    
         
            +
                #
         
     | 
| 
      
 174 
     | 
    
         
            +
                # @overload find(id)
         
     | 
| 
      
 175 
     | 
    
         
            +
                #   Retrieve a single Elastictastic document
         
     | 
| 
      
 176 
     | 
    
         
            +
                #   
         
     | 
| 
      
 177 
     | 
    
         
            +
                #   @param [String] id ID of the document
         
     | 
| 
      
 178 
     | 
    
         
            +
                #   @return [Elastictastic::BasicDocument] The document with that ID, or nil if not found
         
     | 
| 
      
 179 
     | 
    
         
            +
                #
         
     | 
| 
      
 180 
     | 
    
         
            +
                # @overload find(ids)
         
     | 
| 
      
 181 
     | 
    
         
            +
                #   Retrieve a collection of Elastictastic documents by ID. This will
         
     | 
| 
      
 182 
     | 
    
         
            +
                #   return an Array even if the ids argument is a one-element Array.
         
     | 
| 
      
 183 
     | 
    
         
            +
                #
         
     | 
| 
      
 184 
     | 
    
         
            +
                #   @param [Array] ids Document IDs
         
     | 
| 
      
 185 
     | 
    
         
            +
                #   @return [Array] Collection of documents with the given IDs
         
     | 
| 
      
 186 
     | 
    
         
            +
                #
         
     | 
| 
       101 
187 
     | 
    
         
             
                def find(*ids)
         
     | 
| 
       102 
188 
     | 
    
         
             
                  #TODO support combining this with other filters/query
         
     | 
| 
       103 
189 
     | 
    
         
             
                  force_array = ::Array === ids.first
         
     | 
| 
       104 
190 
     | 
    
         
             
                  ids = ids.flatten
         
     | 
| 
       105 
     | 
    
         
            -
                  if  
     | 
| 
       106 
     | 
    
         
            -
                    find_many_in_many_indices(*ids)
         
     | 
| 
       107 
     | 
    
         
            -
                  elsif ids.length == 1
         
     | 
| 
      
 191 
     | 
    
         
            +
                  if ids.length == 1
         
     | 
| 
       108 
192 
     | 
    
         
             
                    instance = find_one(ids.first)
         
     | 
| 
       109 
193 
     | 
    
         
             
                    force_array ? [instance] : instance
         
     | 
| 
       110 
194 
     | 
    
         
             
                  else
         
     | 
| 
         @@ -128,6 +212,12 @@ module Elastictastic 
     | 
|
| 
       128 
212 
     | 
    
         
             
                  RUBY
         
     | 
| 
       129 
213 
     | 
    
         
             
                end
         
     | 
| 
       130 
214 
     | 
    
         | 
| 
      
 215 
     | 
    
         
            +
                def routing(routing)
         
     | 
| 
      
 216 
     | 
    
         
            +
                  scope = scoped({})
         
     | 
| 
      
 217 
     | 
    
         
            +
                  scope.routing = routing
         
     | 
| 
      
 218 
     | 
    
         
            +
                  scope
         
     | 
| 
      
 219 
     | 
    
         
            +
                end
         
     | 
| 
      
 220 
     | 
    
         
            +
             
     | 
| 
       131 
221 
     | 
    
         
             
                def method_missing(method, *args, &block)
         
     | 
| 
       132 
222 
     | 
    
         
             
                  if ::Enumerable.method_defined?(method)
         
     | 
| 
       133 
223 
     | 
    
         
             
                    each.__send__(method, *args, &block)
         
     | 
| 
         @@ -142,11 +232,76 @@ module Elastictastic 
     | 
|
| 
       142 
232 
     | 
    
         | 
| 
       143 
233 
     | 
    
         
             
                def inspect
         
     | 
| 
       144 
234 
     | 
    
         
             
                  inspected = "#{@clazz.name}:#{@index.name}"
         
     | 
| 
       145 
     | 
    
         
            -
                  inspected << @search.params 
     | 
| 
      
 235 
     | 
    
         
            +
                  inspected << ::Elastictastic.json_encode(@search.params) unless @search.params.empty?
         
     | 
| 
       146 
236 
     | 
    
         
             
                  inspected
         
     | 
| 
       147 
237 
     | 
    
         
             
                end
         
     | 
| 
       148 
238 
     | 
    
         | 
| 
      
 239 
     | 
    
         
            +
                #
         
     | 
| 
      
 240 
     | 
    
         
            +
                # @private
         
     | 
| 
      
 241 
     | 
    
         
            +
                #
         
     | 
| 
      
 242 
     | 
    
         
            +
                def response=(response)
         
     | 
| 
      
 243 
     | 
    
         
            +
                  self.counts = response
         
     | 
| 
      
 244 
     | 
    
         
            +
                  @materialized_hits = materialize_hits(response['hits']['hits'])
         
     | 
| 
      
 245 
     | 
    
         
            +
                end
         
     | 
| 
      
 246 
     | 
    
         
            +
             
     | 
| 
      
 247 
     | 
    
         
            +
                #
         
     | 
| 
      
 248 
     | 
    
         
            +
                # @private
         
     | 
| 
      
 249 
     | 
    
         
            +
                #
         
     | 
| 
      
 250 
     | 
    
         
            +
                def counts=(response)
         
     | 
| 
      
 251 
     | 
    
         
            +
                  @count ||= response['hits']['total']
         
     | 
| 
      
 252 
     | 
    
         
            +
                  if response['facets']
         
     | 
| 
      
 253 
     | 
    
         
            +
                    @all_facets ||= ::Hashie::Mash.new(response['facets'])
         
     | 
| 
      
 254 
     | 
    
         
            +
                  end
         
     | 
| 
      
 255 
     | 
    
         
            +
                end
         
     | 
| 
      
 256 
     | 
    
         
            +
             
     | 
| 
      
 257 
     | 
    
         
            +
                #
         
     | 
| 
      
 258 
     | 
    
         
            +
                # @private
         
     | 
| 
      
 259 
     | 
    
         
            +
                #
         
     | 
| 
      
 260 
     | 
    
         
            +
                def find_one(id, params = {})
         
     | 
| 
      
 261 
     | 
    
         
            +
                  data = ::Elastictastic.client.
         
     | 
| 
      
 262 
     | 
    
         
            +
                    get(index, type, id, params_for_find_one.merge(params.stringify_keys))
         
     | 
| 
      
 263 
     | 
    
         
            +
                  return nil if data['exists'] == false
         
     | 
| 
      
 264 
     | 
    
         
            +
                  case data['status']
         
     | 
| 
      
 265 
     | 
    
         
            +
                  when nil
         
     | 
| 
      
 266 
     | 
    
         
            +
                    materialize_hit(data)
         
     | 
| 
      
 267 
     | 
    
         
            +
                  when 404
         
     | 
| 
      
 268 
     | 
    
         
            +
                    nil
         
     | 
| 
      
 269 
     | 
    
         
            +
                  end
         
     | 
| 
      
 270 
     | 
    
         
            +
                end
         
     | 
| 
      
 271 
     | 
    
         
            +
             
     | 
| 
      
 272 
     | 
    
         
            +
                def multi_get_params
         
     | 
| 
      
 273 
     | 
    
         
            +
                  {
         
     | 
| 
      
 274 
     | 
    
         
            +
                    '_type' => type,
         
     | 
| 
      
 275 
     | 
    
         
            +
                    '_index' => @index.name
         
     | 
| 
      
 276 
     | 
    
         
            +
                  }.tap do |params|
         
     | 
| 
      
 277 
     | 
    
         
            +
                    params['fields'] = ::Kernel.Array(@search['fields']) if @search['fields']
         
     | 
| 
      
 278 
     | 
    
         
            +
                    if @routing
         
     | 
| 
      
 279 
     | 
    
         
            +
                      params['routing'] = @routing
         
     | 
| 
      
 280 
     | 
    
         
            +
                    elsif @clazz.routing_required?
         
     | 
| 
      
 281 
     | 
    
         
            +
                      ::Kernel.raise ::Elastictastic::MissingParameter,
         
     | 
| 
      
 282 
     | 
    
         
            +
                        "Must specify routing parameter to look up #{@clazz.name} by ID"
         
     | 
| 
      
 283 
     | 
    
         
            +
                    end
         
     | 
| 
      
 284 
     | 
    
         
            +
                  end
         
     | 
| 
      
 285 
     | 
    
         
            +
                end
         
     | 
| 
      
 286 
     | 
    
         
            +
             
     | 
| 
      
 287 
     | 
    
         
            +
                def multi_search_headers
         
     | 
| 
      
 288 
     | 
    
         
            +
                  {'type' => type, 'index' => @index.name}.tap do |params|
         
     | 
| 
      
 289 
     | 
    
         
            +
                    params['routing'] = @routing if @routing
         
     | 
| 
      
 290 
     | 
    
         
            +
                  end
         
     | 
| 
      
 291 
     | 
    
         
            +
                end
         
     | 
| 
      
 292 
     | 
    
         
            +
             
     | 
| 
      
 293 
     | 
    
         
            +
                #
         
     | 
| 
      
 294 
     | 
    
         
            +
                # @private
         
     | 
| 
      
 295 
     | 
    
         
            +
                #
         
     | 
| 
      
 296 
     | 
    
         
            +
                def materialize_hit(hit)
         
     | 
| 
      
 297 
     | 
    
         
            +
                  @clazz.new.tap do |result|
         
     | 
| 
      
 298 
     | 
    
         
            +
                    result.parent = @parent if @parent
         
     | 
| 
      
 299 
     | 
    
         
            +
                    result.elasticsearch_hit = hit
         
     | 
| 
      
 300 
     | 
    
         
            +
                  end
         
     | 
| 
      
 301 
     | 
    
         
            +
                end
         
     | 
| 
      
 302 
     | 
    
         
            +
             
     | 
| 
       149 
303 
     | 
    
         
             
                protected
         
     | 
| 
      
 304 
     | 
    
         
            +
                attr_writer :routing
         
     | 
| 
       150 
305 
     | 
    
         | 
| 
       151 
306 
     | 
    
         
             
                def search(search_params = {})
         
     | 
| 
       152 
307 
     | 
    
         
             
                  ::Elastictastic.client.search(
         
     | 
| 
         @@ -160,9 +315,11 @@ module Elastictastic 
     | 
|
| 
       160 
315 
     | 
    
         
             
                private
         
     | 
| 
       161 
316 
     | 
    
         | 
| 
       162 
317 
     | 
    
         
             
                def search_all
         
     | 
| 
       163 
     | 
    
         
            -
                   
     | 
| 
       164 
     | 
    
         
            -
                   
     | 
| 
       165 
     | 
    
         
            -
                   
     | 
| 
      
 318 
     | 
    
         
            +
                  return @materialized_hits if defined? @materialized_hits
         
     | 
| 
      
 319 
     | 
    
         
            +
                  search_params = {:search_type => 'query_then_fetch'}
         
     | 
| 
      
 320 
     | 
    
         
            +
                  search_params[:routing] = @routing if @routing
         
     | 
| 
      
 321 
     | 
    
         
            +
                  self.response = search(search_params)
         
     | 
| 
      
 322 
     | 
    
         
            +
                  @materialized_hits
         
     | 
| 
       166 
323 
     | 
    
         
             
                end
         
     | 
| 
       167 
324 
     | 
    
         | 
| 
       168 
325 
     | 
    
         
             
                def search_in_batches(&block)
         
     | 
| 
         @@ -170,8 +327,10 @@ module Elastictastic 
     | 
|
| 
       170 
327 
     | 
    
         
             
                  scope_with_size = self.size(size)
         
     | 
| 
       171 
328 
     | 
    
         
             
                  begin
         
     | 
| 
       172 
329 
     | 
    
         
             
                    scope = scope_with_size.from(from)
         
     | 
| 
       173 
     | 
    
         
            -
                     
     | 
| 
       174 
     | 
    
         
            -
                     
     | 
| 
      
 330 
     | 
    
         
            +
                    params = {:search_type => 'query_then_fetch'}
         
     | 
| 
      
 331 
     | 
    
         
            +
                    params[:routing] = @routing if @routing
         
     | 
| 
      
 332 
     | 
    
         
            +
                    response = scope.search(params)
         
     | 
| 
      
 333 
     | 
    
         
            +
                    self.counts = response
         
     | 
| 
       175 
334 
     | 
    
         
             
                    yield materialize_hits(response['hits']['hits'])
         
     | 
| 
       176 
335 
     | 
    
         
             
                    from += size
         
     | 
| 
       177 
336 
     | 
    
         
             
                    @count ||= scope.count
         
     | 
| 
         @@ -184,6 +343,7 @@ module Elastictastic 
     | 
|
| 
       184 
343 
     | 
    
         
             
                    :scroll => "#{batch_options[:ttl] || 60}s",
         
     | 
| 
       185 
344 
     | 
    
         
             
                    :size => batch_options[:batch_size] || ::Elastictastic.config.default_batch_size
         
     | 
| 
       186 
345 
     | 
    
         
             
                  }
         
     | 
| 
      
 346 
     | 
    
         
            +
                  scroll_options[:routing] = @routing if @routing
         
     | 
| 
       187 
347 
     | 
    
         
             
                  scan_response = ::Elastictastic.client.search(
         
     | 
| 
       188 
348 
     | 
    
         
             
                    @index,
         
     | 
| 
       189 
349 
     | 
    
         
             
                    @clazz.type,
         
     | 
| 
         @@ -201,51 +361,22 @@ module Elastictastic 
     | 
|
| 
       201 
361 
     | 
    
         
             
                  end until response['hits']['hits'].empty?
         
     | 
| 
       202 
362 
     | 
    
         
             
                end
         
     | 
| 
       203 
363 
     | 
    
         | 
| 
       204 
     | 
    
         
            -
                def populate_counts 
     | 
| 
       205 
     | 
    
         
            -
                   
     | 
| 
       206 
     | 
    
         
            -
                  @ 
     | 
| 
       207 
     | 
    
         
            -
                   
     | 
| 
       208 
     | 
    
         
            -
                    @all_facets ||= ::Hashie::Mash.new(response['facets'])
         
     | 
| 
       209 
     | 
    
         
            -
                  end
         
     | 
| 
      
 364 
     | 
    
         
            +
                def populate_counts
         
     | 
| 
      
 365 
     | 
    
         
            +
                  params = {:search_type => 'count'}
         
     | 
| 
      
 366 
     | 
    
         
            +
                  params[:routing] = @routing if @routing
         
     | 
| 
      
 367 
     | 
    
         
            +
                  self.counts = search(params)
         
     | 
| 
       210 
368 
     | 
    
         
             
                end
         
     | 
| 
       211 
369 
     | 
    
         | 
| 
       212 
     | 
    
         
            -
                def  
     | 
| 
       213 
     | 
    
         
            -
                  data = ::Elastictastic.client.get(index, type, id, params_for_find_one)
         
     | 
| 
       214 
     | 
    
         
            -
                  return nil if data['exists'] == false
         
     | 
| 
       215 
     | 
    
         
            -
                  case data['status']
         
     | 
| 
       216 
     | 
    
         
            -
                  when nil
         
     | 
| 
       217 
     | 
    
         
            -
                    materialize_hit(data)
         
     | 
| 
       218 
     | 
    
         
            -
                  when 404
         
     | 
| 
       219 
     | 
    
         
            -
                    nil
         
     | 
| 
       220 
     | 
    
         
            -
                  end
         
     | 
| 
       221 
     | 
    
         
            -
                end
         
     | 
| 
       222 
     | 
    
         
            -
             
     | 
| 
       223 
     | 
    
         
            -
                def find_many(ids)
         
     | 
| 
      
 370 
     | 
    
         
            +
                def find_many(ids, params = {})
         
     | 
| 
       224 
371 
     | 
    
         
             
                  docspec = ids.map do |id|
         
     | 
| 
       225 
     | 
    
         
            -
                    { '_id' => id }.merge!(params_for_find_many)
         
     | 
| 
      
 372 
     | 
    
         
            +
                    { '_id' => id }.merge!(params_for_find_many).
         
     | 
| 
      
 373 
     | 
    
         
            +
                      merge!(params.stringify_keys)
         
     | 
| 
       226 
374 
     | 
    
         
             
                  end
         
     | 
| 
       227 
375 
     | 
    
         
             
                  materialize_hits(
         
     | 
| 
       228 
376 
     | 
    
         
             
                    ::Elastictastic.client.mget(docspec, index, type)['docs']
         
     | 
| 
       229 
377 
     | 
    
         
             
                  ).map { |result, hit| result }
         
     | 
| 
       230 
378 
     | 
    
         
             
                end
         
     | 
| 
       231 
379 
     | 
    
         | 
| 
       232 
     | 
    
         
            -
                def find_many_in_many_indices(ids_by_index)
         
     | 
| 
       233 
     | 
    
         
            -
                  docs = []
         
     | 
| 
       234 
     | 
    
         
            -
                  ids_by_index.each_pair do |index, ids|
         
     | 
| 
       235 
     | 
    
         
            -
                    ::Kernel.Array(ids).each do |id|
         
     | 
| 
       236 
     | 
    
         
            -
                      docs << doc = {
         
     | 
| 
       237 
     | 
    
         
            -
                        '_id' => id.to_s,
         
     | 
| 
       238 
     | 
    
         
            -
                        '_type' => type,
         
     | 
| 
       239 
     | 
    
         
            -
                        '_index' => index
         
     | 
| 
       240 
     | 
    
         
            -
                      }
         
     | 
| 
       241 
     | 
    
         
            -
                      doc['fields'] = ::Kernel.Array(@search['fields']) if @search['fields']
         
     | 
| 
       242 
     | 
    
         
            -
                    end
         
     | 
| 
       243 
     | 
    
         
            -
                  end
         
     | 
| 
       244 
     | 
    
         
            -
                  materialize_hits(
         
     | 
| 
       245 
     | 
    
         
            -
                    ::Elastictastic.client.mget(docs)['docs']
         
     | 
| 
       246 
     | 
    
         
            -
                  ).map { |result, hit| result }
         
     | 
| 
       247 
     | 
    
         
            -
                end
         
     | 
| 
       248 
     | 
    
         
            -
             
     | 
| 
       249 
380 
     | 
    
         
             
                def params_for_find_one
         
     | 
| 
       250 
381 
     | 
    
         
             
                  params_for_find.tap do |params|
         
     | 
| 
       251 
382 
     | 
    
         
             
                    params['fields'] &&= params['fields'].join(',')
         
     | 
| 
         @@ -259,6 +390,12 @@ module Elastictastic 
     | 
|
| 
       259 
390 
     | 
    
         
             
                def params_for_find
         
     | 
| 
       260 
391 
     | 
    
         
             
                  {}.tap do |params|
         
     | 
| 
       261 
392 
     | 
    
         
             
                    params['fields'] = ::Kernel.Array(@search['fields']) if @search['fields']
         
     | 
| 
      
 393 
     | 
    
         
            +
                    if @routing
         
     | 
| 
      
 394 
     | 
    
         
            +
                      params['routing'] = @routing
         
     | 
| 
      
 395 
     | 
    
         
            +
                    elsif @clazz.routing_required?
         
     | 
| 
      
 396 
     | 
    
         
            +
                      ::Kernel.raise ::Elastictastic::MissingParameter,
         
     | 
| 
      
 397 
     | 
    
         
            +
                        "Must specify routing parameter to look up #{@clazz.name} by ID"
         
     | 
| 
      
 398 
     | 
    
         
            +
                    end
         
     | 
| 
       262 
399 
     | 
    
         
             
                  end
         
     | 
| 
       263 
400 
     | 
    
         
             
                end
         
     | 
| 
       264 
401 
     | 
    
         | 
| 
         @@ -272,12 +409,5 @@ module Elastictastic 
     | 
|
| 
       272 
409 
     | 
    
         
             
                    end
         
     | 
| 
       273 
410 
     | 
    
         
             
                  end
         
     | 
| 
       274 
411 
     | 
    
         
             
                end
         
     | 
| 
       275 
     | 
    
         
            -
             
     | 
| 
       276 
     | 
    
         
            -
                def materialize_hit(hit)
         
     | 
| 
       277 
     | 
    
         
            -
                  @clazz.new.tap do |result|
         
     | 
| 
       278 
     | 
    
         
            -
                    result.parent_collection = @parent_collection if @parent_collection
         
     | 
| 
       279 
     | 
    
         
            -
                    result.elasticsearch_hit = hit
         
     | 
| 
       280 
     | 
    
         
            -
                  end
         
     | 
| 
       281 
     | 
    
         
            -
                end
         
     | 
| 
       282 
412 
     | 
    
         
             
              end
         
     | 
| 
       283 
413 
     | 
    
         
             
            end
         
     | 
| 
         @@ -1,6 +1,9 @@ 
     | 
|
| 
       1 
1 
     | 
    
         
             
            module Elastictastic
         
     | 
| 
       2 
2 
     | 
    
         
             
              module ServerError
         
     | 
| 
       3 
     | 
    
         
            -
                 
     | 
| 
      
 3 
     | 
    
         
            +
                ERROR_PATTERN = /^([A-Z][A-Za-z]*)(?::\s*)?(.*)$/
         
     | 
| 
      
 4 
     | 
    
         
            +
                NESTED_PATTERN = /^.*nested:\s+(.*)$/
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
      
 6 
     | 
    
         
            +
                class ServerError < Elastictastic::Error
         
     | 
| 
       4 
7 
     | 
    
         
             
                  attr_accessor :status
         
     | 
| 
       5 
8 
     | 
    
         
             
                end
         
     | 
| 
       6 
9 
     | 
    
         | 
| 
         @@ -10,6 +13,22 @@ module Elastictastic 
     | 
|
| 
       10 
13 
     | 
    
         
             
                      const_set(name, error)
         
     | 
| 
       11 
14 
     | 
    
         
             
                    end
         
     | 
| 
       12 
15 
     | 
    
         
             
                  end
         
     | 
| 
      
 16 
     | 
    
         
            +
             
     | 
| 
      
 17 
     | 
    
         
            +
                  def [](server_message, status = nil)
         
     | 
| 
      
 18 
     | 
    
         
            +
                    match = ERROR_PATTERN.match(server_message)
         
     | 
| 
      
 19 
     | 
    
         
            +
                    if match
         
     | 
| 
      
 20 
     | 
    
         
            +
                      if (nested_match = NESTED_PATTERN.match(match[2]))
         
     | 
| 
      
 21 
     | 
    
         
            +
                        return self[nested_match[1], status]
         
     | 
| 
      
 22 
     | 
    
         
            +
                      else
         
     | 
| 
      
 23 
     | 
    
         
            +
                        clazz = Elastictastic::ServerError.const_get(match[1])
         
     | 
| 
      
 24 
     | 
    
         
            +
                        error = clazz.new(match[2])
         
     | 
| 
      
 25 
     | 
    
         
            +
                        error.status = status
         
     | 
| 
      
 26 
     | 
    
         
            +
                        error
         
     | 
| 
      
 27 
     | 
    
         
            +
                      end
         
     | 
| 
      
 28 
     | 
    
         
            +
                    else
         
     | 
| 
      
 29 
     | 
    
         
            +
                      Elastictastic::ServerError::ServerError.new(server_message)
         
     | 
| 
      
 30 
     | 
    
         
            +
                    end
         
     | 
| 
      
 31 
     | 
    
         
            +
                  end
         
     | 
| 
       13 
32 
     | 
    
         
             
                end
         
     | 
| 
       14 
33 
     | 
    
         
             
              end
         
     | 
| 
       15 
34 
     | 
    
         
             
            end
         
     |