Class: ElasticsearchRecord::Result
- Inherits:
-
Object
- Object
- ElasticsearchRecord::Result
- Includes:
- Enumerable
- Defined in:
- lib/elasticsearch_record/result.rb
Instance Attribute Summary collapse
-
#column_types ⇒ Object
readonly
Returns the value of attribute column_types.
-
#columns ⇒ Object
readonly
Returns the value of attribute columns.
-
#response ⇒ Object
readonly
Returns the value of attribute response.
Class Method Summary collapse
-
.empty(async: false) ⇒ ElasticsearchRecord::Result (frozen), ActiveRecord::FutureResult::Complete (frozen)
creates an empty response.
Instance Method Summary collapse
- #[](idx) ⇒ Object
-
#aggregations ⇒ ActiveSupport::HashWithIndifferentAccess, Hash
returns the response RAW aggregations hash.
-
#buckets ⇒ ActiveSupport::HashWithIndifferentAccess
returns the (nested) bucket values (and aggregated values) from the response aggregations.
-
#cancel ⇒ Object
used by ActiveRecord.
-
#cast_values(type_overrides = {}) ⇒ Object
used by ActiveRecord for "pluck".
-
#each(&block) ⇒ Object
Calls the given block once for each element in row collection, passing row as parameter.
-
#empty? ⇒ Boolean
Returns true if there are no records, otherwise false.
-
#hits ⇒ ActiveSupport::HashWithIndifferentAccess, Hash
returns the response RAW hits hash.
-
#includes_column?(name) ⇒ Boolean
Returns true if this result set includes the column named
name. -
#initialize(response, columns = [], column_types = {}) ⇒ Result
constructor
initializes a new result object.
-
#last(n = nil) ⇒ Object
Returns the last record(s) from the computed_results collection.
-
#length ⇒ Integer
Returns the number of elements in the response array.
-
#result ⇒ String
returns the response result string.
-
#results ⇒ Array
Returns the RAW
_sourcedata from each hit. -
#rows ⇒ Array
returns an array of all rows.
-
#to_ary ⇒ Object
(also: #to_a)
Returns an array of hashes representing each row record.
-
#took ⇒ Integer
returns the response duration time.
-
#total ⇒ Integer
returns the response total value.
Constructor Details
#initialize(response, columns = [], column_types = {}) ⇒ Result
initializes a new result object
25 26 27 28 29 30 31 32 33 34 |
# File 'lib/elasticsearch_record/result.rb', line 25 def initialize(response, columns = [], column_types = {}) # contains either the response or creates an empty hash (if nil) @response = response.presence || {} # used to build computed_results @columns = columns # used to cast values @column_types = column_types end |
Instance Attribute Details
#column_types ⇒ Object (readonly)
Returns the value of attribute column_types.
19 20 21 |
# File 'lib/elasticsearch_record/result.rb', line 19 def column_types @column_types end |
#columns ⇒ Object (readonly)
Returns the value of attribute columns.
19 20 21 |
# File 'lib/elasticsearch_record/result.rb', line 19 def columns @columns end |
#response ⇒ Object (readonly)
Returns the value of attribute response.
19 20 21 |
# File 'lib/elasticsearch_record/result.rb', line 19 def response @response end |
Class Method Details
.empty(async: false) ⇒ ElasticsearchRecord::Result (frozen), ActiveRecord::FutureResult::Complete (frozen)
creates an empty response
11 12 13 14 15 16 17 |
# File 'lib/elasticsearch_record/result.rb', line 11 def self.empty(async: false) if async EMPTY_ASYNC else EMPTY end end |
Instance Method Details
#[](idx) ⇒ Object
166 167 168 |
# File 'lib/elasticsearch_record/result.rb', line 166 def [](idx) computed_results[idx] end |
#aggregations ⇒ ActiveSupport::HashWithIndifferentAccess, Hash
returns the response RAW aggregations hash.
103 104 105 |
# File 'lib/elasticsearch_record/result.rb', line 103 def aggregations response['aggregations']&.with_indifferent_access || {} end |
#buckets ⇒ ActiveSupport::HashWithIndifferentAccess
returns the (nested) bucket values (and aggregated values) from the response aggregations.
109 110 111 112 113 114 115 116 |
# File 'lib/elasticsearch_record/result.rb', line 109 def buckets # aggregations are already a hash with key => data, but to prevent reference manipulation on the hash # we have to create a new one here... aggregations.reduce({}) { |buckets, (key, agg)| buckets[key] = _resolve_bucket(agg) buckets }.with_indifferent_access end |
#cancel ⇒ Object
used by ActiveRecord
176 177 178 |
# File 'lib/elasticsearch_record/result.rb', line 176 def cancel # :nodoc: self end |
#cast_values(type_overrides = {}) ⇒ Object
used by ActiveRecord for "pluck"
181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 |
# File 'lib/elasticsearch_record/result.rb', line 181 def cast_values(type_overrides = {}) # fast escape, if no hits are available return [] unless response['hits'] # HINT: This is separated to avoid allocating a (nested) array per row if columns.one? # resolve the column key key = columns.first # resolve type from overrides or +#column_type+ method type = type_overrides.is_a?(Array) ? type_overrides.first : column_type(key, type_overrides) # EDGE-case for metadata fields if ActiveRecord::ConnectionAdapters::ElasticsearchAdapter..include?(key) # directly read from doc response['hits']['hits'].map { |doc| type.deserialize(doc[key]) } else results.map do |result| type.deserialize(result[key]) end end else # resolve types from overrides or +#column_type+ method types = type_overrides.is_a?(Array) ? type_overrides : columns.map { |name| column_type(name, type_overrides) } size = types.size # EDGE-case for metadata fields - they have to be resolved from the doc, so we merge them into the +_source+ rows = if (ActiveRecord::ConnectionAdapters::ElasticsearchAdapter. & columns).any? response['hits']['hits'].map { |doc| (doc['_source'] || {}).merge(doc.slice(*ActiveRecord::ConnectionAdapters::ElasticsearchAdapter.)) } else response['hits']['hits'].map { |doc| doc['_source'] || {} } end rows.map do |result| Array.new(size) { |i| types[i].deserialize(result[columns[i]]) } end end end |
#each(&block) ⇒ Object
Calls the given block once for each element in row collection, passing row as parameter.
Returns an Enumerator if no block is given.
146 147 148 149 150 151 152 |
# File 'lib/elasticsearch_record/result.rb', line 146 def each(&block) if block_given? computed_results.each(&block) else computed_results.to_enum { @computed_results.size } end end |
#empty? ⇒ Boolean
Returns true if there are no records, otherwise false.
155 156 157 |
# File 'lib/elasticsearch_record/result.rb', line 155 def empty? length == 0 end |
#hits ⇒ ActiveSupport::HashWithIndifferentAccess, Hash
returns the response RAW hits hash. PLEASE NOTE: Does not return the nested hits (+response['hits']+) array!
97 98 99 |
# File 'lib/elasticsearch_record/result.rb', line 97 def hits response['hits']&.with_indifferent_access || {} end |
#includes_column?(name) ⇒ Boolean
Returns true if this result set includes the column named name.
used by ActiveRecord
120 121 122 |
# File 'lib/elasticsearch_record/result.rb', line 120 def includes_column?(name) @columns&.include?(name) end |
#last(n = nil) ⇒ Object
Returns the last record(s) from the computed_results collection.
171 172 173 |
# File 'lib/elasticsearch_record/result.rb', line 171 def last(n = nil) n ? computed_results.last(n) : computed_results.last end |
#length ⇒ Integer
Returns the number of elements in the response array.
Either uses the hits length, the responses length (msearch) or the length of the
tabular value rows (SQL / ES|QL).
128 129 130 131 132 133 134 135 136 137 138 139 140 |
# File 'lib/elasticsearch_record/result.rb', line 128 def length if response.key?('hits') response['hits']['hits'].length elsif response.key?('responses') # used by +msearch+ response['responses'].length elsif _tabular? # used by +sql+ & +esql+ _tabular_values.length else 0 end end |
#result ⇒ String
returns the response result string
44 45 46 |
# File 'lib/elasticsearch_record/result.rb', line 44 def result response['result'] || '' end |
#results ⇒ Array
Returns the RAW _source data from each hit.
PLEASE NOTE: The array will only contain the RAW data from each _source (meta info like '_id' or '_score' are not included)
59 60 61 62 63 64 65 66 67 68 69 70 |
# File 'lib/elasticsearch_record/result.rb', line 59 def results # IMPORTANT: check against missing hits without any '_source' node. # This happens if the Elasticsearch query has the +_source:false+ flag! if response['hits'] response['hits']['hits'].map { |doc| doc['_source'] || {} } elsif _tabular? # a tabular (+SQL+ / +ES|QL+) response has no '_source' node - the row values are the data _results_from_tabular else [] end end |
#rows ⇒ Array
returns an array of all rows.
=> All result values, depending on the provided columns.
The rows is used by the ActiveRecord ConnectionAdapters and must not be removed!
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
# File 'lib/elasticsearch_record/result.rb', line 76 def rows # a tabular (+SQL+ / +ES|QL+) response is ALREADY positional - and it is positional to the # response's own columns, not to the (requested) +columns+ of the query. return _tabular_values if _tabular? # IMPORTANT: without provided +columns+ we cannot build positional rows - mapping over an # empty +columns+ array would return an empty array per hit and silently lose all data. # In this case we fall back to the raw +_source+ values. return results.map(&:values) if columns.blank? results.map { |doc| columns.map { |column| doc[column] } } end |
#to_ary ⇒ Object Also known as: to_a
Returns an array of hashes representing each row record.
160 161 162 |
# File 'lib/elasticsearch_record/result.rb', line 160 def to_ary computed_results end |
#took ⇒ Integer
returns the response duration time
38 39 40 |
# File 'lib/elasticsearch_record/result.rb', line 38 def took response['took'] end |
#total ⇒ Integer
returns the response total value.
either chops the total value directly from response, from hits or aggregations.
51 52 53 54 |
# File 'lib/elasticsearch_record/result.rb', line 51 def total # chop total from response and not from the generated data @total ||= _total end |