elasticsearch_record 1.6.0 → 1.7.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b29c6db7894f8365eb5a5922633a4adf53a793006c3ffa2fb381dd9ae171b124
4
- data.tar.gz: 72c7f4260b76be5743e061838df5051006c82a883172d29f2e0442b6215ac4ed
3
+ metadata.gz: 52f19a4a5802d333a04d2c72e4a7a51c3f0bfc501c0b8b379e6afb44d1076aca
4
+ data.tar.gz: ac2eb76b596b4705feac42612fb0e11d530f684750ee780471c765172a69ea7f
5
5
  SHA512:
6
- metadata.gz: 7e09f30a077c81524c800a5694947d947da7a0a9273a4304592221d2c191c8a8582fbd94e65990ddf21cdbb23d74d5e7d4e47e53e14139c362fda91468aae182
7
- data.tar.gz: bb03f9c4fa2749ccd23be70de65a1480b2d0a7cfa89ef51f9a3c3c2cd7e0810708e9e1e8050d7de033bfc670d5a127c75349f1f1380578246107395746e41652
6
+ metadata.gz: 68b0cc2c384b7751c271aa1d3f8b37af778d20af1ca6e42a967b97454ab2121a0606150977690a9153b58567d2172c5e08cfe2adbf7578e3051c60edf0c4a1a4
7
+ data.tar.gz: bf240b8ccd09364d6237900854c824080068cd6822400f7538dabedd85491cb64dbe45b86725aa353fe9fc598e4e2d4837935775e132af11215ea767daf2b7e1
data/.yardopts CHANGED
@@ -1,6 +1,6 @@
1
1
  --embed-mixins
2
2
  --markup=markdown
3
- --files docs/*.*
3
+ --files docs/*
4
4
  --plugin relative_markdown_links
5
5
  --plugin activesupport-concern
6
6
  --exclude lib/elasticsearch_record/patches
data/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
  [![Documentation](https://img.shields.io/badge/docs-rdoc.info-blue.svg)](http://rubydoc.info/gems/elasticsearch_record)
5
5
 
6
6
  [![Gem Version](https://badge.fury.io/rb/elasticsearch_record.svg)](https://badge.fury.io/rb/elasticsearch_record)
7
- [![License](https://img.shields.io/github/license/ruby-smart/elasticsearch_record)](docs/LICENSE.txt)
7
+ [![License](https://img.shields.io/github/license/ruby-smart/elasticsearch_record)](docs/LICENSE)
8
8
 
9
9
  ActiveRecord adapter for Elasticsearch
10
10
 
@@ -14,8 +14,28 @@ _ElasticsearchRecord is a ActiveRecord adapter and provides similar functionalit
14
14
 
15
15
  **PLEASE NOTE:**
16
16
 
17
- - Specs & documentation are still missing, but will follow.
18
- - Currently supports ActiveRecord ~> 7.0 + Elasticsearch >= 7.17
17
+ - This is the `rails-7-0-stable`-branch, which only supports rails **7.0** _(see section 'Rails_Versions' for supported versions)_
18
+ - supports ActiveRecord ~> 7.0 + Elasticsearch >= 7.17
19
+
20
+ -----
21
+
22
+ ## Rails versions
23
+
24
+ Supported rails versions:
25
+
26
+ ### Rails 7.1:
27
+ _(since gem version 1.8)_
28
+
29
+ https://github.com/ruby-smart/elasticsearch_record/tree/rails-7-1-stable
30
+
31
+ [![rails-7-1-stable](https://img.shields.io/badge/rails-7.1.stable-orange.svg)](https://github.com/ruby-smart/elasticsearch_record/tree/rails-7-1-stable)
32
+
33
+ ### Rails 7.0:
34
+ _(until gem version 1.7)_
35
+
36
+ https://github.com/ruby-smart/elasticsearch_record/tree/rails-7-0-stable
37
+
38
+ [![rails-7-0-stable](https://img.shields.io/badge/rails-7.0.stable-orange.svg)](https://github.com/ruby-smart/elasticsearch_record/tree/rails-7-0-stable)
19
39
 
20
40
  -----
21
41
 
@@ -24,7 +44,11 @@ _ElasticsearchRecord is a ActiveRecord adapter and provides similar functionalit
24
44
  Add this line to your application's Gemfile:
25
45
 
26
46
  ```ruby
27
- gem 'elasticsearch_record'
47
+ gem 'elasticsearch_record', '~> 1.7'
48
+
49
+ # alternative
50
+ gem 'elasticsearch_record', git: 'https://github.com/ruby-smart/elasticsearch_record', branch: 'rails-7-0-stable'
51
+
28
52
  ```
29
53
 
30
54
  And then execute:
@@ -235,6 +259,19 @@ total = scope.total
235
259
  # > 3335
236
260
  ```
237
261
 
262
+ ### Available core query methods
263
+
264
+ - find_by_sql
265
+ - find_by_query
266
+ - find_by_esql
267
+ - esql
268
+ - msearch
269
+ - search
270
+
271
+ _see simple documentation about these methods @ {ElasticsearchRecord::Querying rubydoc}_
272
+
273
+ _(also see @ [github](https://github.com/ruby-smart/elasticsearch_record/blob/main/lib/elasticsearch_record/querying.rb) )_
274
+
238
275
  ### Available query/relation chain methods
239
276
  - kind
240
277
  - configure
@@ -252,7 +289,9 @@ total = scope.total
252
289
  - aggs_only!
253
290
  - total_only!
254
291
 
255
- _see simple documentation about these methods @ [rubydoc](https://rubydoc.info/gems/elasticsearch_record/ElasticsearchRecord/Relation/QueryMethods)_
292
+ _see simple documentation about these methods @ {ElasticsearchRecord::Relation::QueryMethods rubydoc}_
293
+
294
+ _(also see @ [github](https://github.com/ruby-smart/elasticsearch_record/blob/main/lib/elasticsearch_record/relation/query_methods.rb) )_
256
295
 
257
296
  ### Available calculation methods
258
297
  - percentiles
@@ -262,9 +301,16 @@ _see simple documentation about these methods @ [rubydoc](https://rubydoc.info/g
262
301
  - minimum
263
302
  - maximum
264
303
  - sum
304
+ - boxplot
305
+ - stats
306
+ - string_stats
307
+ - matrix_stats
308
+ - median_absolute_deviation
265
309
  - calculate
266
310
 
267
- _see simple documentation about these methods @ [rubydoc](https://rubydoc.info/gems/elasticsearch_record/ElasticsearchRecord/Relation/CalculationMethods)_
311
+ _see simple documentation about these methods @ {ElasticsearchRecord::Relation::CalculationMethods rubydoc}_
312
+
313
+ _(also see @ [github](https://github.com/ruby-smart/elasticsearch_record/blob/main/lib/elasticsearch_record/relation/calculation_methods.rb) )_
268
314
 
269
315
  ### Available result methods
270
316
  - aggregations
@@ -279,7 +325,9 @@ _see simple documentation about these methods @ [rubydoc](https://rubydoc.info/g
279
325
  - pit_results
280
326
  - pit_delete
281
327
 
282
- _see simple documentation about these methods @ [rubydoc](https://rubydoc.info/gems/elasticsearch_record/ElasticsearchRecord/Relation/ResultMethods)_
328
+ _see simple documentation about these methods @ {ElasticsearchRecord::Relation::ResultMethods rubydoc}_
329
+
330
+ _(also see @ [github](https://github.com/ruby-smart/elasticsearch_record/blob/main/lib/elasticsearch_record/relation/result_methods.rb) )_
283
331
 
284
332
  ### Additional methods
285
333
  - to_query
@@ -620,7 +668,7 @@ This project is intended to be a safe, welcoming space for collaboration, and co
620
668
 
621
669
  The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
622
670
 
623
- A copy of the [LICENSE](docs/LICENSE.txt) can be found @ the docs.
671
+ A copy of the [LICENSE](docs/LICENSE) can be found @ the docs.
624
672
 
625
673
  ## Code of Conduct
626
674
 
data/docs/CHANGELOG.md CHANGED
@@ -1,5 +1,20 @@
1
1
  # ElasticsearchRecord - CHANGELOG
2
2
 
3
+ ## [1.7.1] - 2024-01-09
4
+ * [fix] `ElasticsearchRecord::Relation` calculation methods return with different nodes
5
+ * [ref] `ElasticsearchRecord::Relation#calculate` removes default value of `node`
6
+ * [ref] `ActiveRecord::ConnectionAdapters::ElasticsearchAdapter#api` prevents inaccurate variable interpretation of `log`
7
+
8
+ ## [1.7.0] - 2024-01-09
9
+ * [add] `ElasticsearchRecord::Relation#boxplot` calculation method
10
+ * [add] `ElasticsearchRecord::Relation#stats` calculation method
11
+ * [add] `ElasticsearchRecord::Relation#string_stats` calculation method
12
+ * [add] `ElasticsearchRecord::Relation#matrix_stats` calculation method
13
+ * [add] `ElasticsearchRecord::Relation#median_absolute_deviation` calculation method
14
+ * [add] `ElasticsearchRecord::Base#esql` + `ElasticsearchRecord::Base#find_by_esql` to support `ES|QL` queries
15
+ * [add] new repository branch `rails-7-0-stable` to support different rails versions
16
+ * [ref] minor code optimizations & documentation changes
17
+
3
18
  ## [1.6.0] - 2023-08-11
4
19
  * [add] `ElasticsearchRecord::Base#undelegate_id_attribute_with` method to support a temporary 'undelegation' (used to create a new record)
5
20
  * [add] `ElasticsearchRecord::Relation#timeout` to directly provide the timeout-parameter to the query
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2022 Ruby Smart
3
+ Copyright (c) 2024 Ruby Smart
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -238,7 +238,7 @@ module ActiveRecord # :nodoc:
238
238
  # resolve the API target
239
239
  target = namespace == :core ? @connection : @connection.__send__(namespace)
240
240
 
241
- log("#{namespace}.#{action}", arguments, name, async: async, log: log) do
241
+ __send__(:log, "#{namespace}.#{action}", arguments, name, async: async, log: log) do
242
242
  response = ActiveSupport::Dependencies.interlock.permit_concurrent_loads do
243
243
  target.__send__(action, arguments)
244
244
  end
@@ -8,8 +8,8 @@ module ElasticsearchRecord
8
8
 
9
9
  module VERSION
10
10
  MAJOR = 1
11
- MINOR = 6
12
- TINY = 0
11
+ MINOR = 7
12
+ TINY = 1
13
13
  PRE = nil
14
14
 
15
15
  STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".")
@@ -12,6 +12,7 @@ module ElasticsearchRecord
12
12
  TYPE_SEARCH = :search
13
13
  TYPE_MSEARCH = :msearch
14
14
  TYPE_SQL = :sql
15
+ TYPE_ESQL = :esql
15
16
 
16
17
  # -- DOCUMENT TYPES ------------------------------------------------------------------------------------------------
17
18
  TYPE_CREATE = :create
@@ -34,7 +35,7 @@ module ElasticsearchRecord
34
35
  # includes valid types only
35
36
  TYPES = [
36
37
  # -- QUERY TYPES
37
- TYPE_COUNT, TYPE_SEARCH, TYPE_MSEARCH, TYPE_SQL,
38
+ TYPE_COUNT, TYPE_SEARCH, TYPE_MSEARCH, TYPE_SQL, TYPE_ESQL,
38
39
  # -- DOCUMENT TYPES
39
40
  TYPE_CREATE, TYPE_UPDATE, TYPE_UPDATE_BY_QUERY, TYPE_DELETE, TYPE_DELETE_BY_QUERY,
40
41
 
@@ -46,7 +47,7 @@ module ElasticsearchRecord
46
47
 
47
48
  # includes reading types only
48
49
  READ_TYPES = [
49
- TYPE_COUNT, TYPE_SEARCH, TYPE_MSEARCH, TYPE_SQL
50
+ TYPE_COUNT, TYPE_SEARCH, TYPE_MSEARCH, TYPE_SQL, TYPE_ESQL
50
51
  ].freeze
51
52
 
52
53
  # defines a body to be executed if the query fails - +(none)+
@@ -60,6 +61,7 @@ module ElasticsearchRecord
60
61
  # if no special type is defined, it simply uses +[:core,self.type]+
61
62
  GATES = {
62
63
  TYPE_SQL => [:sql, :query],
64
+ TYPE_ESQL => [:esql, :query],
63
65
  TYPE_INDEX_CREATE => [:indices, :create],
64
66
  TYPE_INDEX_CLONE => [:indices, :clone],
65
67
  TYPE_INDEX_UPDATE_MAPPING => [:indices, :put_mapping],
@@ -118,6 +120,12 @@ module ElasticsearchRecord
118
120
  self
119
121
  end
120
122
 
123
+ # returns true, if the query failed
124
+ # @return [Boolean]
125
+ def failed?
126
+ self.status == STATUS_FAILED
127
+ end
128
+
121
129
  # returns true, if the query is valid (e.g. index & type defined)
122
130
  # @return [Boolean]
123
131
  def valid?
@@ -143,7 +151,7 @@ module ElasticsearchRecord
143
151
  # failed queried will return the related +FAILED_BODIES+ or +{}+ as fallback
144
152
  # @return [Hash, nil]
145
153
  def body
146
- return (FAILED_BODIES[self.type].presence || {}) if self.status == STATUS_FAILED
154
+ return (FAILED_BODIES[self.type].presence || {}) if failed?
147
155
 
148
156
  @body
149
157
  end
@@ -77,7 +77,42 @@ module ElasticsearchRecord
77
77
  _load_from_sql(_query_by_sql(query), &block)
78
78
  end
79
79
 
80
- # executes a msearch by provided +RAW+ queries
80
+ # ES|QL query API
81
+ # Returns search results for an ES|QL (Elasticsearch query language) query.
82
+ #
83
+ # @param [String] esql
84
+ # @param [Proc] block
85
+ def find_by_esql(esql, &block)
86
+ # build new query
87
+ query = ElasticsearchRecord::Query.new(
88
+ type: ElasticsearchRecord::Query::TYPE_ESQL,
89
+ body: { query: esql },
90
+ # IMPORTANT: Always provide all columns
91
+ columns: source_column_names)
92
+
93
+ _load_from_sql(_query_by_sql(query), &block)
94
+ end
95
+
96
+ # executes a +esql+ by provided *ES|SL* query
97
+ # Does NOT instantiate records.
98
+ # @param [String] esql
99
+ # @param [Boolean] async (default: false)
100
+ def esql(esql, async: false)
101
+ # build new query
102
+ query = ElasticsearchRecord::Query.new(
103
+ type: ElasticsearchRecord::Query::TYPE_ESQL,
104
+ body: { query: esql },
105
+ # IMPORTANT: Always provide all columns
106
+ columns: source_column_names)
107
+
108
+ connection.exec_query(query, "#{name} ES|QL", async: async)
109
+ end
110
+
111
+
112
+ # executes a +msearch+ by provided *RAW* queries.
113
+ # Does NOT instantiate records.
114
+ # @param [Array<String>] queries
115
+ # @param [Boolean] async (default: false)
81
116
  def msearch(queries, async: false)
82
117
  # build new msearch query
83
118
  query = ElasticsearchRecord::Query.new(
@@ -45,6 +45,84 @@ module ElasticsearchRecord
45
45
  end
46
46
  end
47
47
 
48
+ # A boxplot metrics aggregation that computes boxplot of numeric values extracted from the aggregated documents.
49
+ # These values can be generated from specific numeric or histogram fields in the documents.
50
+ #
51
+ # The boxplot aggregation returns essential information for making a box plot:
52
+ # *minimum*, *maximum*, *median*, *first quartile* (25th percentile) and *third quartile* (75th percentile) values.
53
+ #
54
+ # Person.all.boxplot(:age)
55
+ # > {
56
+ # "min": 0.0,
57
+ # "max": 990.0,
58
+ # "q1": 167.5,
59
+ # "q2": 445.0,
60
+ # "q3": 722.5,
61
+ # "lower": 0.0,
62
+ # "upper": 990.0
63
+ # }
64
+ #
65
+ # @see https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-metrics-boxplot-aggregation.html
66
+ #
67
+ # @param [Symbol, String] column_name
68
+ def boxplot(column_name)
69
+ calculate(:boxplot, column_name)
70
+ end
71
+
72
+ # A multi-value metrics aggregation that computes stats over numeric values extracted from the aggregated documents. #
73
+ # The stats that are returned consist of: *min*, *max*, *sum*, *count* and *avg*.
74
+ #
75
+ # Person.all.stats(:age)
76
+ # > {
77
+ # "count": 10,
78
+ # "min": 0.0,
79
+ # "max": 990.0,
80
+ # "sum": 16859,
81
+ # "avg": 75.5
82
+ # }
83
+ #
84
+ # @see https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-metrics-stats-aggregation.html
85
+ #
86
+ # @param [Symbol, String] column_name
87
+ def stats(column_name)
88
+ calculate(:stats, column_name)
89
+ end
90
+
91
+ # A multi-value metrics aggregation that computes statistics over string values extracted from the aggregated documents.
92
+ # These values can be retrieved either from specific keyword fields.
93
+ #
94
+ # Person.all.string_stats(:name)
95
+ # > {
96
+ # "count": 5,
97
+ # "min_length": 24,
98
+ # "max_length": 30,
99
+ # "avg_length": 28.8,
100
+ # "entropy": 3.94617750050791
101
+ # }
102
+ #
103
+ # @see https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-metrics-string-stats-aggregation.html
104
+ #
105
+ # @param [Symbol, String] column_name
106
+ def string_stats(column_name)
107
+ calculate(:string_stats, column_name)
108
+ end
109
+
110
+ # The matrix_stats aggregation is a numeric aggregation that computes the following statistics over a set of document fields:
111
+ # *count* Number of per field samples included in the calculation.
112
+ # *mean* The average value for each field.
113
+ # *variance* Per field Measurement for how spread out the samples are from the mean.
114
+ # *skewness* Per field measurement quantifying the asymmetric distribution around the mean.
115
+ # *kurtosis* Per field measurement quantifying the shape of the distribution.
116
+ # *covariance* A matrix that quantitatively describes how changes in one field are associated with another.
117
+ # *correlation* The covariance matrix scaled to a range of -1 to 1, inclusive. Describes the relationship between field distributions.
118
+ #
119
+ # @see https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-matrix-stats-aggregation.html
120
+ #
121
+ # @param [Array<Symbol|String>] column_names
122
+ def matrix_stats(*column_names)
123
+ calculate(:matrix_stats, *column_names)
124
+ end
125
+
48
126
  # A multi-value metrics aggregation that calculates one or more
49
127
  # percentiles over numeric values extracted from the aggregated documents.
50
128
  # Returns a hash with empty values (but keys still exists) if there is no row.
@@ -59,6 +137,9 @@ module ElasticsearchRecord
59
137
  # "95.0" => 2021.0,
60
138
  # "99.0" => 2022.0
61
139
  # }
140
+ #
141
+ # @see https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-metrics-percentile-aggregation.html
142
+ #
62
143
  # @param [Symbol, String] column_name
63
144
  def percentiles(column_name)
64
145
  calculate(:percentiles, column_name, node: :values)
@@ -81,10 +162,13 @@ module ElasticsearchRecord
81
162
  # "95.0" => 2021.0,
82
163
  # "99.0" => 2022.0
83
164
  # }
165
+ #
166
+ # @see https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-metrics-percentile-rank-aggregation.html
167
+ #
84
168
  # @param [Symbol, String] column_name
85
169
  # @param [Array] values
86
170
  def percentile_ranks(column_name, values)
87
- calculate(:percentiles, column_name, opts: { values: values }, node: :values)
171
+ calculate(:percentile_ranks, column_name, opts: { values: values }, node: :values)
88
172
  end
89
173
 
90
174
  # Calculates the cardinality on a given column. Returns +0+ if there's no row.
@@ -92,18 +176,22 @@ module ElasticsearchRecord
92
176
  # Person.all.cardinality(:age)
93
177
  # > 12
94
178
  #
179
+ # @see https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-metrics-cardinality-aggregation.html
180
+ #
95
181
  # @param [Symbol, String] column_name
96
182
  def cardinality(column_name)
97
- calculate(:cardinality, column_name)
183
+ calculate(:cardinality, column_name, node: :value)
98
184
  end
99
185
 
100
186
  # Calculates the average value on a given column. Returns +nil+ if there's no row. See #calculate for examples with options.
101
187
  #
102
188
  # Person.all.average(:age) # => 35.8
103
189
  #
190
+ # @see https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-metrics-avg-aggregation.html
191
+ #
104
192
  # @param [Symbol, String] column_name
105
193
  def average(column_name)
106
- calculate(:avg, column_name)
194
+ calculate(:avg, column_name, node: :value)
107
195
  end
108
196
 
109
197
  # Calculates the minimum value on a given column. The value is returned
@@ -112,9 +200,11 @@ module ElasticsearchRecord
112
200
  # Person.all.minimum(:age)
113
201
  # > 7
114
202
  #
203
+ # @see https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-metrics-min-aggregation.html
204
+ #
115
205
  # @param [Symbol, String] column_name
116
206
  def minimum(column_name)
117
- calculate(:min, column_name)
207
+ calculate(:min, column_name, node: :value)
118
208
  end
119
209
 
120
210
  # Calculates the maximum value on a given column. The value is returned
@@ -123,9 +213,28 @@ module ElasticsearchRecord
123
213
  #
124
214
  # Person.all.maximum(:age) # => 93
125
215
  #
216
+ # @see https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-metrics-max-aggregation.html
217
+ #
126
218
  # @param [Symbol, String] column_name
127
219
  def maximum(column_name)
128
- calculate(:max, column_name)
220
+ calculate(:max, column_name, node: :value)
221
+ end
222
+
223
+ # This single-value aggregation approximates the median absolute deviation of its search results.
224
+ # Median absolute deviation is a measure of variability. It is a robust statistic,
225
+ # meaning that it is useful for describing data that may have outliers, or may not be normally distributed.
226
+ # For such data it can be more descriptive than standard deviation.
227
+ #
228
+ # It is calculated as the median of each data point’s deviation from the median of the entire sample.
229
+ # That is, for a random variable X, the median absolute deviation is median(|median(X) - Xi|).
230
+ #
231
+ # Person.all.median_absolute_deviation(:age) # => 91
232
+ #
233
+ # @see https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-metrics-median-absolute-deviation-aggregation.html
234
+ #
235
+ # @param [Symbol, String] column_name
236
+ def median_absolute_deviation(column_name)
237
+ calculate(:median_absolute_deviation, column_name)
129
238
  end
130
239
 
131
240
  # Calculates the sum of values on a given column. The value is returned
@@ -134,24 +243,34 @@ module ElasticsearchRecord
134
243
  #
135
244
  # Person.all.sum(:age) # => 4562
136
245
  #
246
+ # @see https://www.elastic.co/guide/en/elasticsearch/reference/current/search-aggregations-metrics-sum-aggregation.html
247
+ #
137
248
  # @param [Symbol, String] column_name (optional)
138
249
  def sum(column_name)
139
- calculate(:sum, column_name)
250
+ calculate(:sum, column_name, node: :value)
140
251
  end
141
252
 
142
- # creates a aggregation with the provided metric (e.g. :sum) and column.
253
+ # creates a aggregation with the provided metric (e.g. :sum) and columns.
143
254
  # returns the metric node (default: :value) from the aggregations result.
144
255
  # @param [Symbol, String] metric
145
- # @param [Symbol, String] column
256
+ # @param [Array<Symbol|String>] columns
146
257
  # @param [Hash] opts - additional arguments that get merged with the metric definition
147
- # @param [Symbol] node (default :value)
148
- def calculate(metric, column, opts: {}, node: :value)
149
- metric_key = "#{column}_#{metric}"
258
+ # @param [Symbol] node (default: nil)
259
+ def calculate(metric, *columns, opts: {}, node: nil)
260
+ metric_key = "calculate_#{metric}"
150
261
 
151
262
  # spawn a new aggregation and return the aggs
152
- response = aggregate(metric_key, { metric => { field: column }.merge(opts) }).aggregations
263
+ response = if columns.size == 1
264
+ aggregate(metric_key, { metric => { field: columns[0] }.merge(opts) }).aggregations
265
+ else
266
+ aggregate(metric_key, { metric => { fields: columns }.merge(opts) }).aggregations
267
+ end
153
268
 
154
- response[metric_key][node]
269
+ if node.present?
270
+ response[metric_key][node]
271
+ else
272
+ response[metric_key]
273
+ end
155
274
  end
156
275
  end
157
276
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: elasticsearch_record
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.6.0
4
+ version: 1.7.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tobias Gonsior
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-08-11 00:00:00.000000000 Z
11
+ date: 2024-01-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -125,7 +125,7 @@ files:
125
125
  - Rakefile
126
126
  - docs/CHANGELOG.md
127
127
  - docs/CODE_OF_CONDUCT.md
128
- - docs/LICENSE.txt
128
+ - docs/LICENSE
129
129
  - elasticsearch_record.gemspec
130
130
  - lib/active_record/connection_adapters/elasticsearch/column.rb
131
131
  - lib/active_record/connection_adapters/elasticsearch/database_statements.rb