Class: ElasticSearch::Response

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Defined in:
lib/elastic_search/response.rb

Overview

The ElasticSearch::Response class wraps a raw ElasticSearch response and decorates it with methods for aggregations, hits, records, pagination, etc.

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(relation, response) ⇒ Response

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

Initializes a new response object for the provided relation and raw ElasticSearch response.



16
17
18
19
# File 'lib/elastic_search/response.rb', line 16

def initialize(relation, response)
  self.relation = relation
  self.response = response
end

Instance Attribute Details

#relationObject

Returns the value of attribute relation



9
10
11
# File 'lib/elastic_search/response.rb', line 9

def relation
  @relation
end

#responseObject

Returns the value of attribute response



9
10
11
# File 'lib/elastic_search/response.rb', line 9

def response
  @response
end

Instance Method Details

#aggregations(name = nil) ⇒ Hash

Returns a single or all aggregations returned by ElasticSearch, depending on whether or not a name is specified. If no name is specified, the raw aggregation hash is simply returned. Contrary, if a name is specified, only this aggregation is returned. Moreover, if a name is specified and the aggregation includes a buckets section, a post-processed aggregation hash is returned.

Examples:

All aggregations

CommentIndex.aggregate(:user_id).aggregations
# => {"user_id"=>{..., "buckets"=>[{"key"=>4922, "doc_count"=>1129}, ...]}

Specific and post-processed aggregations

CommentIndex.aggregate(:user_id).aggregations(:user_id)
# => {4922=>1129, ...}

Returns:

  • (Hash)

    Specific or all aggregations returned by ElasticSearch



297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
# File 'lib/elastic_search/response.rb', line 297

def aggregations(name = nil)
  return response["aggregations"] || {} unless name

  @aggregations ||= {}

  key = name.to_s

  return @aggregations[key] if @aggregations.key?(key)

  @aggregations[key] =
    if response["aggregations"].nil? || response["aggregations"][key].nil?
      Result.new
    elsif response["aggregations"][key]["buckets"].is_a?(Array)
      response["aggregations"][key]["buckets"].each_with_object({}) { |bucket, hash| hash[bucket["key"]] = Result.new(bucket) }
    elsif response["aggregations"][key]["buckets"].is_a?(Hash)
      Result.new response["aggregations"][key]["buckets"]
    else
      Result.new response["aggregations"][key]
    end
end

#current_pageFixnum

Returns the current page number, useful for pagination.

Examples:

CommentIndex.search("hello world").paginate(page: 10).current_page
# => 10

Returns:

  • (Fixnum)

    The current page number



105
106
107
# File 'lib/elastic_search/response.rb', line 105

def current_page
  1 + (relation.offset_value_with_default / relation.limit_value_with_default.to_f).ceil
end

#first_page?Boolean

Returns whether or not the current page is the first page.

Examples:

CommentIndex.paginate(page: 1).first_page?
# => true

CommentIndex.paginate(page: 2).first_page?
# => false

Returns:

  • (Boolean)

    Returns true if the current page is the first page or false otherwise



60
61
62
# File 'lib/elastic_search/response.rb', line 60

def first_page?
  current_page == 1
end

#hitsHash

Returns the hits returned by ElasticSearch.

Examples:

CommentIndex.search("hello world").hits
# => {"total"=>3, "max_score"=>2.34, "hits"=>[{...}, ...]}

Returns:

  • (Hash)

    The hits returned by ElasticSearch



201
202
203
# File 'lib/elastic_search/response.rb', line 201

def hits
  response["hits"]
end

#idsObject

Returns the array of ids returned by ElasticSearch for the current result set, ie the ids listed in the hits section of the response.

Examples:

CommentIndex.match_all.ids # => [20341, 12942, ...]

Returns:

  • The array of ids in the current result set



262
263
264
# File 'lib/elastic_search/response.rb', line 262

def ids
  @ids ||= hits["hits"].map { |hit| hit["_id"] }
end

#last_page?Boolean

Returns whether or not the current page is the last page.

Examples:

CommentIndex.paginate(page: 100).last_page?
# => true

CommentIndex.paginate(page: 1).last_page?
# => false

Returns:

  • (Boolean)

    Returns true if the current page is the last page or false otherwise



76
77
78
# File 'lib/elastic_search/response.rb', line 76

def last_page?
  current_page == total_pages
end

#next_pageFixnum?

Returns the next page number or nil if there is no next page, ie the current page is the last page.

Examples:

CommentIndex.search("hello world").paginate(page: 2).next_page
# => 3

Returns:

  • (Fixnum, nil)

    The next page number



152
153
154
155
156
157
# File 'lib/elastic_search/response.rb', line 152

def next_page
  return nil if current_page >= total_pages
  return 1 if current_page < 1

  return current_page + 1
end

#out_of_range?Boolean

Returns whether or not the current page is out of range, ie. smaller than 1 or larger than #total_pages

Examples:

CommentIndex.paginate(page: 1_000_000).out_of_range?
# => true

CommentIndex.paginate(page: 1).out_of_range?
# => false

Returns:

  • (Boolean)

    Returns true if the current page is out of range



93
94
95
# File 'lib/elastic_search/response.rb', line 93

def out_of_range?
  current_page < 1 || current_page > total_pages
end

#previous_pageFixnum? Also known as: prev_page

Returns the previous page number or nil if no previous page exists, ie if the current page is the first page.

Examples:

CommentIndex.search("hello world").paginate(page: 2).previous_page
# => 1

CommentIndex.search("hello world").paginate(page: 1).previous_page
# => nil

Returns:

  • (Fixnum, nil)

    The previous page number



134
135
136
137
138
139
# File 'lib/elastic_search/response.rb', line 134

def previous_page
  return nil if current_page <= 1
  return total_pages if current_page > total_pages

  current_page - 1
end

#raw_responseHash

Returns the raw response, ie a hash derived from the ElasticSearch JSON response.

Examples:

CommentIndex.search("hello world").raw_response
# => {"took"=>3, "timed_out"=>false, "_shards"=>"..."}

Returns:

  • (Hash)

    The raw response hash



30
31
32
# File 'lib/elastic_search/response.rb', line 30

def raw_response
  response
end

#records(options = {}) ⇒ Array

Returns the database records, usually ActiveRecord objects, depending on the ORM you're using. The records are sorted using the order returned by ElasticSearch.

Examples:

CommentIndex.search("hello world").records # => [#<Comment ...>, ...]

Returns:

  • (Array)

    An array of database records



226
227
228
229
230
231
232
# File 'lib/elastic_search/response.rb', line 226

def records(options = {})
  @records ||= begin
    sort_map = ids.each_with_index.each_with_object({}) { |(id, index), hash| hash[id.to_s] = index }

    scope.to_a.sort_by { |record| sort_map[relation.target.record_id(record).to_s] }
  end
end

#resultsArray

Returns the results, ie hits, wrapped in a ElasticSearch::Result object which basically is a Hashie::Mash. Check out the Hashie docs for further details.

Examples:

CommentIndex.search("hello world").results
# => [#<ElasticSearch::Result ...>, ...]

Returns:

  • (Array)

    An array of results



169
170
171
# File 'lib/elastic_search/response.rb', line 169

def results
  @results ||= hits["hits"].map { |hit| Result.new hit["_source"].merge(hit["highlight"] ? { highlight: hit["highlight"] } : {}) }
end

#scopeObject

Builds and returns a scope for the array of ids in the current result set returned by ElasticSearch, including the eager load, preload and includes associations, if specified. A scope is eg an ActiveRecord::Relation, depending on the ORM you're using.

Examples:

CommentIndex.preload(:user).scope # => #<Comment::ActiveRecord_Relation:0x0...>

Returns:

  • The scope for the array of ids in the current result set



244
245
246
247
248
249
250
251
252
# File 'lib/elastic_search/response.rb', line 244

def scope
  res = relation.target.fetch_records(ids)

  res = res.includes(*relation.includes_values) if relation.includes_values
  res = res.eager_load(*relation.eager_load_values) if relation.eager_load_values
  res = res.preload(*relation.preload_values) if relation.preload_values

  res
end

#scroll_idString

Returns the scroll id returned by ElasticSearch, that can be used in the following request to fetch the next batch of records.

Examples:

CommentIndex.scroll(timeout: "1m").scroll_id #=> "cXVlcnlUaGVuRmV0Y2..."

Returns:

  • (String)

    The scroll id returned by ElasticSearch



213
214
215
# File 'lib/elastic_search/response.rb', line 213

def scroll_id
  response["_scroll_id"]
end

#suggestions(name = nil) ⇒ Hash, Array

Returns the named sugggetion, if a name is specified or alle suggestions.

Examples:

query = CommentIndex.suggest(:suggestion, text: "helo", term: { field: "message" })
query.suggestions # => {"suggestion"=>[{"text"=>...}, ...]}

Named suggestions

query = CommentIndex.suggest(:suggestion, text: "helo", term: { field: "message" })
query.suggestions(:sugestion).first["text"] # => "hello"

Returns:

  • (Hash, Array)

    The named suggestion or all suggestions



185
186
187
188
189
190
191
# File 'lib/elastic_search/response.rb', line 185

def suggestions(name = nil)
  if name
    response["suggest"][name.to_s].first["options"]
  else
    response["suggest"]
  end
end

#tookFixnum

Returns the response time in milliseconds of ElasticSearch specified in the took info of the response.

Examples:

CommentIndex.match_all.took # => 6

Returns:

  • (Fixnum)

    The ElasticSearch response time in milliseconds



276
277
278
# File 'lib/elastic_search/response.rb', line 276

def took
  response["took"]
end

#total_entriesFixnum Also known as: total_count

Returns the total number of results.

Examples:

CommentIndex.search("hello world").total_entries
# => 13

Returns:

  • (Fixnum)

    The total number of results



42
43
44
# File 'lib/elastic_search/response.rb', line 42

def total_entries
  hits["total"]
end

#total_pagesFixnum

Returns the number of total pages for the current pagination settings, ie per page/limit settings.

Examples:

CommentIndex.search("hello world").paginate(per_page: 60).total_pages
# => 5

Returns:

  • (Fixnum)

    The total number of pages



118
119
120
# File 'lib/elastic_search/response.rb', line 118

def total_pages
  [(total_entries / relation.limit_value_with_default.to_f).ceil, 1].max
end