Class: Tire::Results::Collection

Inherits:
Object
  • Object
show all
Includes:
Enumerable, Pagination
Defined in:
lib/tire/results/collection.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Pagination

#current_page, default_per_page, #first_page?, #last_page?, #next_page, #offset, #out_of_bounds?, #per_page, #previous_page, #total_entries, #total_pages

Constructor Details

#initialize(response, options = {}) ⇒ Collection

Returns a new instance of Collection



10
11
12
13
14
15
16
17
18
19
# File 'lib/tire/results/collection.rb', line 10

def initialize(response, options={})
  @response    = response
  @options     = options
  @time        = response['took'].to_i
  @total       = response['hits']['total'].to_i rescue nil
  @facets      = response['facets']
  @suggestions = Suggestions.new(response['suggest']) if response['suggest']
  @max_score   = response['hits']['max_score'].to_f rescue nil
  @wrapper     = options[:wrapper] || Configuration.wrapper
end

Instance Attribute Details

#facetsObject (readonly)

Returns the value of attribute facets



8
9
10
# File 'lib/tire/results/collection.rb', line 8

def facets
  @facets
end

#max_scoreObject (readonly)

Returns the value of attribute max_score



8
9
10
# File 'lib/tire/results/collection.rb', line 8

def max_score
  @max_score
end

#optionsObject (readonly)

Returns the value of attribute options



8
9
10
# File 'lib/tire/results/collection.rb', line 8

def options
  @options
end

#suggestionsObject (readonly)

Returns the value of attribute suggestions



8
9
10
# File 'lib/tire/results/collection.rb', line 8

def suggestions
  @suggestions
end

#timeObject (readonly)

Returns the value of attribute time



8
9
10
# File 'lib/tire/results/collection.rb', line 8

def time
  @time
end

#totalObject (readonly)

Returns the value of attribute total



8
9
10
# File 'lib/tire/results/collection.rb', line 8

def total
  @total
end

Instance Method Details

#__find_records_by_ids(klass, ids) ⇒ Object



156
157
158
# File 'lib/tire/results/collection.rb', line 156

def __find_records_by_ids(klass, ids)
  @options[:load] === true ? klass.find(ids) : klass.find(ids, @options[:load])
end

#__get_results_with_load(hits) ⇒ Object



128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
# File 'lib/tire/results/collection.rb', line 128

def __get_results_with_load(hits)
  return [] if hits.empty?

  records = {}
  @response['hits']['hits'].group_by { |item| item['_type'] }.each do |type, items|
    raise NoMethodError, "You have tried to eager load the model instances, " +
                         "but Tire cannot find the model class because " +
                         "document has no _type property." unless type

    begin
      klass = type.camelize.constantize
    rescue NameError => e
      raise NameError, "You have tried to eager load the model instances, but " +
                       "Tire cannot find the model class '#{type.camelize}' " +
                       "based on _type '#{type}'.", e.backtrace
    end

    records[type] = Array(__find_records_by_ids klass, items.map { |h| h['_id'] })
  end

  # Reorder records to preserve the order from search results
  @response['hits']['hits'].map do |item|
    records[item['_type']].detect do |record|
      record.id.to_s == item['_id'].to_s
    end
  end
end

#__get_results_without_load(hits) ⇒ Object



103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/tire/results/collection.rb', line 103

def __get_results_without_load(hits)
  if @wrapper == Hash
    hits
  else
    hits.map do |h|
      document = {}

      # Update the document with fields and/or source
      document.update h['_source'] if h['_source']
      document.update __parse_fields__(h['fields']) if h['fields']

      # Set document ID
      document['id'] = h['_id']

      # Update the document with meta information
      ['_score', '_type', '_index', '_version', 'sort', 'highlight', '_explanation'].each do |key|
        document.update key => h[key]
      end

      # Return an instance of the "wrapper" class
      @wrapper.new(document)
    end
  end
end

#__parse_fields__(fields = {}) ⇒ Object

Handles _source prefixed fields properly: strips the prefix and converts fields to nested Hashes



83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
# File 'lib/tire/results/collection.rb', line 83

def __parse_fields__(fields={})
  ( fields ||= {} ).clone.each_pair do |key,value|
    next unless key.to_s =~ /_source/                 # Skip regular JSON immediately

    keys = key.to_s.split('.').reject { |n| n == '_source' }
    fields.delete(key)

    result = {}
    path = []

    keys.each do |name|
      path << name
      eval "result[:#{path.join('][:')}] ||= {}"
      eval "result[:#{path.join('][:')}] = #{value.inspect}" if keys.last == name
    end
    fields.update result
  end
  fields
end

#as_json(options = nil) ⇒ Object



65
66
67
# File 'lib/tire/results/collection.rb', line 65

def as_json(options=nil)
  to_a.map { |item| item.as_json(options) }
end

#each(&block) ⇒ Object

Iterates over the results collection



35
36
37
# File 'lib/tire/results/collection.rb', line 35

def each(&block)
  results.each(&block)
end

#each_with_hit(&block) ⇒ Object

Iterates over the results collection and yields the result object (Item or model instance) and the hit -- raw Elasticsearch response parsed as a Hash



43
44
45
# File 'lib/tire/results/collection.rb', line 43

def each_with_hit(&block)
  results.zip(@response['hits']['hits']).each(&block)
end

#empty?Boolean

Returns:

  • (Boolean)


47
48
49
# File 'lib/tire/results/collection.rb', line 47

def empty?
  results.empty?
end

#errorObject



69
70
71
# File 'lib/tire/results/collection.rb', line 69

def error
  @response['error']
end

#failure?Boolean

Returns:

  • (Boolean)


77
78
79
# File 'lib/tire/results/collection.rb', line 77

def failure?
  ! success?
end

#resultsObject



21
22
23
24
25
26
27
28
29
30
31
# File 'lib/tire/results/collection.rb', line 21

def results
  return [] if failure?
  @results ||= begin
    hits = @response['hits']['hits'].map { |d| d.update '_type' => Utils.unescape(d['_type']) }
    unless @options[:load]
      __get_results_without_load(hits)
    else
      __get_results_with_load(hits)
    end
  end
end

#sizeObject Also known as: length



51
52
53
# File 'lib/tire/results/collection.rb', line 51

def size
  results.size
end

#slice(*args) ⇒ Object Also known as: []



56
57
58
# File 'lib/tire/results/collection.rb', line 56

def slice(*args)
  results.slice(*args)
end

#success?Boolean

Returns:

  • (Boolean)


73
74
75
# File 'lib/tire/results/collection.rb', line 73

def success?
  error.to_s.empty?
end

#to_aryObject



61
62
63
# File 'lib/tire/results/collection.rb', line 61

def to_ary
  results
end