jay_api 28.3.0 → 28.4.0

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: 07ffb602dd7c52159b2142a00f06401d0326ae8e82e05ba24c61f96d35347d8c
4
- data.tar.gz: 7f0f39ca31de378467d2914e3322fd83f6fad7a0b2185a30c94582d213d04439
3
+ metadata.gz: c1af59670e04b1508c6773538b8d9d0478f1971e80755ea526012eaa44f4717c
4
+ data.tar.gz: d23445b944fd8ef0cea8fd628536132fe2cd024ec315b286223b08ecb2c57452
5
5
  SHA512:
6
- metadata.gz: 8bc9fc4c9631aac5a504600ccabd68ff875e7027682f83b47830608a6578cc7a73702333be180b4dd9c7b5d9d637c32b1ef6d86a6519ba5ef8a40706b0a5d397
7
- data.tar.gz: 290b96e8925ee9bbff77e469bdd8299291317639dfd37ea345e1fb88e608c45b1d799015dd6d94592a300e24a97d1aab34df7de4a3ebb8c7ef014b4a09b2e2ed
6
+ metadata.gz: f6805dc6330cdb960f50af2321112572f9959da7789e02c2810231df24b7a5176686754bb488234e4f64659dbdbdc078985564e5987780cd66e93aaca0e5d0e4
7
+ data.tar.gz: ad80fac10a256c1ff8061cc6822fe9d89763e86f9e710cf0b9e7a8f103f864d4dfd24051c90727fb7fc664a0251503a97515beb1d2cd890b3a4cd43a50066490
data/CHANGELOG.md CHANGED
@@ -8,6 +8,12 @@ Please mark backwards incompatible changes with an exclamation mark at the start
8
8
 
9
9
  ## [Unreleased]
10
10
 
11
+ ## [28.4.0] - 2025-08-26
12
+
13
+ ### Added
14
+ - The `Elasticsearch::Indexes` class. A class which allows multiple indexes to
15
+ be used (fed or queried) at the same time.
16
+
11
17
  ## [28.3.0] - 2025-06-05
12
18
 
13
19
  ### Added
@@ -19,8 +19,8 @@ module JayAPI
19
19
 
20
20
  def_delegators :index, :index_name
21
21
 
22
- # @param [JayAPI::Elasticsearch::Index] index The elasticsearch index on
23
- # which to execute asynchronous operations
22
+ # @param [JayAPI::Elasticsearch::Indexable] index The elasticsearch
23
+ # index or indexes on which to execute asynchronous operations
24
24
  def initialize(index)
25
25
  @index = index
26
26
  end
@@ -1,57 +1,28 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'active_support'
4
- require 'active_support/json' # Needed because ActiveSupport 6 doesn't include it's own JSON module. 🤦
5
- require 'active_support/core_ext/hash/indifferent_access'
6
- require 'active_support/core_ext/hash/keys'
7
- require 'elasticsearch'
8
- require 'logging'
9
-
10
- require_relative 'errors/elasticsearch_error'
11
- require_relative 'async'
12
- require_relative 'query_results'
13
- require_relative 'response'
14
- require_relative 'batch_counter'
15
- require_relative 'search_after_results'
3
+ require_relative 'indexable'
16
4
 
17
5
  module JayAPI
18
6
  module Elasticsearch
19
7
  # Represents an Elasticsearch index. Allows data to be pushed to it one
20
8
  # record at a time or in batches of the specified size.
21
9
  class Index
22
- attr_reader :client, :index_name, :batch_size
23
-
24
- # Default type for documents indexed with the #index method.
25
- DEFAULT_DOC_TYPE = 'nested'
10
+ include ::JayAPI::Elasticsearch::Indexable
26
11
 
27
- # Supported document types (for the #index method)
28
- SUPPORTED_TYPES = [DEFAULT_DOC_TYPE, nil].freeze
29
-
30
- # :reek:ControlParameter (want to avoid the creating of the logger on method definition)
31
- # Creates a new instance of the class.
32
12
  # @param [JayAPI::Elasticsearch::Client] client The Elasticsearch Client object.
33
13
  # @param [String] index_name The name of the Elasticsearch index.
34
- # @param [Integer] batch_size The size of the batch. When this number of
35
- # items are pushed into the index they are flushed to the
36
- # Elasticsearch instance.
14
+ # @param [Integer] batch_size The size of the batch. When this many items
15
+ # are pushed into the index they are flushed to the Elasticsearch
16
+ # instance.
37
17
  # @param [Logging::Logger, nil] logger The logger object to use, if
38
18
  # none is given a new one will be created.
39
19
  def initialize(client:, index_name:, batch_size: 100, logger: nil)
40
- @logger = logger || Logging.logger[self]
41
-
42
- @client = client
43
- @index_name = index_name
44
- @batch_size = batch_size
45
-
46
- @batch = []
20
+ super(client: client, index_names: [index_name], batch_size: batch_size, logger: logger)
47
21
  end
48
22
 
49
- # Pushes a record into the index. (This does not send the record to the
50
- # Elasticsearch instance, only puts it into the send queue).
51
- # @param [Hash] data The data to be pushed to the index.
52
- def push(data)
53
- @batch << { index: { _index: index_name, _type: 'nested', data: data } }
54
- flush! if @batch.size >= batch_size
23
+ # @return [String] The name of the Elasticsearch index.
24
+ def index_name
25
+ @index_name ||= index_names.first
55
26
  end
56
27
 
57
28
  # Sends a record to the Elasticsearch instance right away.
@@ -59,8 +30,8 @@ module JayAPI
59
30
  # @param [String, nil] type The type of the document. When set to +nil+
60
31
  # the decision is left to Elasticsearch's API. Which will normally
61
32
  # default to +_doc+.
62
- # @return [Hash] A hash with information about the created document. An
63
- # example of such Hash is:
33
+ # @return [Hash] A Hash containing information about the created document.
34
+ # An example of such Hash is:
64
35
  #
65
36
  # {
66
37
  # "_index" => "xyz01_unit_test",
@@ -76,147 +47,7 @@ module JayAPI
76
47
  # For information on the contents of this Hash please see:
77
48
  # https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-index_.html#docs-index-api-response-body
78
49
  def index(data, type: DEFAULT_DOC_TYPE)
79
- raise ArgumentError, "Unsupported type: '#{type}'" unless SUPPORTED_TYPES.include?(type)
80
-
81
- client.index index: index_name, type: type, body: data
82
- end
83
-
84
- # Performs a query on the index.
85
- # For more information on how to build the query please refer to the
86
- # Elasticsearch DSL query:
87
- # https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl.html
88
- # @param [Hash] query The query to perform.
89
- # @param [JayAPI::Elasticsearch::BatchCounter, nil] batch_counter Object keeping track of batches.
90
- # @param [Symbol, nil] type Type of query, at the moment either nil or :search_after.
91
- # @return [JayAPI::Elasticsearch::QueryResults] The query results.
92
- # @raise [Elasticsearch::Transport::Transport::ServerError] If the
93
- # query fails.
94
- def search(query, batch_counter: nil, type: nil)
95
- begin
96
- response = Response.new(client.search(index: index_name, body: query))
97
- rescue ::Elasticsearch::Transport::Transport::Errors::BadRequest
98
- logger.error "The 'search' query is invalid: #{JSON.pretty_generate(query)}"
99
- raise
100
- end
101
- query_results(query, response, batch_counter, type)
102
- end
103
-
104
- # Sends whatever is currently in the send queue to the Elasticsearch
105
- # instance and clears the queue.
106
- def flush
107
- return unless @batch.any?
108
-
109
- flush!
110
- end
111
-
112
- # Returns the number of elements currently on the send queue.
113
- # @return [Integer] The number of items in the send queue.
114
- def queue_size
115
- @batch.size
116
- end
117
-
118
- # Delete the documents matching the given query from the Index.
119
- # For more information on how to build the query please refer to the
120
- # Elasticsearch DSL documentation:
121
- # https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl.html
122
- # https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-delete-by-query.html
123
- # @param [Hash] query The delete query
124
- # @param [Integer] slices Number of slices to cut the operation into for
125
- # faster processing (i.e., run the operation in parallel)
126
- # @param [Boolean] wait_for_completion False if Elasticsearch should not
127
- # wait for completion and perform the request asynchronously, true if it
128
- # should wait for completion (i.e., run the operation asynchronously)
129
- # @return [Hash] A Hash that details the results of the operation
130
- # @example Returned Hash (with `wait_for_completion: true`):
131
- # {
132
- # took: 103,
133
- # timed_out: false,
134
- # total: 76,
135
- # deleted: 76,
136
- # batches: 1,
137
- # version_conflicts: 0,
138
- # noops: 0,
139
- # retries: { bulk: 0, search: 0 },
140
- # throttled_millis: 0,
141
- # requests_per_second: 1.0,
142
- # throttled_until_millis: 0,
143
- # failures: []
144
- # }
145
- # @example Returned Hash (with `wait_for_completion: false`):
146
- # {
147
- # task: "B5oDyEsHQu2Q-wpbaMSMTg:577388264"
148
- # }
149
- # @raise [Elasticsearch::Transport::Transport::ServerError] If the
150
- # query fails.
151
- def delete_by_query(query, slices: nil, wait_for_completion: true)
152
- request_params = { index: index_name, body: query }.tap do |params|
153
- params.merge!(slices: slices) if slices
154
- params.merge!(wait_for_completion: false) unless wait_for_completion
155
- end
156
-
157
- client.delete_by_query(**request_params).deep_symbolize_keys
158
- end
159
-
160
- # Deletes asynchronously the documents matching the given query from the
161
- # Index.
162
- # For more information on how to build the query please refer to the
163
- # Elasticsearch DSL documentation:
164
- # https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl.html
165
- # https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-delete-by-query.html
166
- # @param [Hash] query The delete query
167
- # @param [Integer, String] slices Number of slices to cut the operation
168
- # into for faster processing (i.e., run the operation in parallel). Use
169
- # "auto" to make elasticsearch decide how many slices to divide into
170
- # @return [Concurrent::Promise] The eventual value returned from the single
171
- # completion of the delete operation
172
- def delete_by_query_async(query, slices: nil)
173
- async.delete_by_query(query, slices: slices)
174
- end
175
-
176
- private
177
-
178
- attr_reader :logger, :batch
179
-
180
- # Flushes the current send queue to the Elasticsearch instance and
181
- # clears the queue.
182
- def flush!
183
- logger.info "Pushing data to Elasticsearch (#{batch.size} records)..."
184
- response = client.bulk body: batch
185
-
186
- handle_errors(response) if response['errors']
187
-
188
- logger.info 'Done'
189
- @batch = []
190
- end
191
-
192
- # @param [Hash] query The elastic search query.
193
- # @param [JayAPI::Elasticsearch::Response] response The response to the query.
194
- # @param [JayAPI::Elasticsearch::BatchCounter, nil] batch_counter Object keeping track of batches.
195
- # @param [Symbol, nil] type Type of query, at the moment either nil or :search_after.
196
- # @return [QueryResults]
197
- def query_results(query, response, batch_counter, type)
198
- (type == :search_after ? SearchAfterResults : QueryResults).new(
199
- index: self,
200
- query: query,
201
- response: response,
202
- batch_counter: BatchCounter.create_or_update(batch_counter, query, response.size)
203
- )
204
- end
205
-
206
- # Scans the Elasticsearch response in search for the first item that has
207
- # en erroneous state and raises an error including the error details.
208
- # @param [Hash] response The response returned by the Elasticsearch client.
209
- # @raise [Errors::ElasticsearchError] Is always raised.
210
- def handle_errors(response)
211
- error_item = response['items'].find { |item| item['index']['error'] }
212
-
213
- raise Errors::ElasticsearchError,
214
- "An error occurred when pushing the data to Elasticsearch:\n#{error_item['index']['error'].inspect}"
215
- end
216
-
217
- # @return [JayAPI::Elasticsearch::Async]
218
- def async
219
- @async ||= JayAPI::Elasticsearch::Async.new(self)
50
+ super.first
220
51
  end
221
52
  end
222
53
  end
@@ -0,0 +1,225 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support'
4
+ require 'active_support/json' # Needed because ActiveSupport 6 doesn't include it's own JSON module. 🤦
5
+ require 'active_support/core_ext/hash/keys'
6
+ require 'elasticsearch'
7
+ require 'logging'
8
+
9
+ require_relative 'async'
10
+ require_relative 'batch_counter'
11
+ require_relative 'errors/elasticsearch_error'
12
+ require_relative 'query_results'
13
+ require_relative 'response'
14
+ require_relative 'search_after_results'
15
+
16
+ module JayAPI
17
+ module Elasticsearch
18
+ # This module houses the Elasticsearch methods that can be used with a
19
+ # single or with multiple indexes. Its main purpose is to avoid code
20
+ # repetition between classes.
21
+ module Indexable
22
+ # Default type for documents indexed with the #index method.
23
+ DEFAULT_DOC_TYPE = 'nested'
24
+
25
+ # Supported document types (for the #index method)
26
+ SUPPORTED_TYPES = [DEFAULT_DOC_TYPE, nil].freeze
27
+
28
+ attr_reader :client, :batch_size
29
+
30
+ # :reek:ControlParameter (want to avoid the creating of the logger on method definition)
31
+ # @param [JayAPI::Elasticsearch::Client] client The Elasticsearch Client object.
32
+ # @param [Array<String>] index_names The names of the Elasticsearch indexes.
33
+ # @param [Integer] batch_size The size of the batch. When this many items
34
+ # are pushed into the index they are flushed to the Elasticsearch
35
+ # instance.
36
+ # @param [Logging::Logger, nil] logger The logger object to use, if
37
+ # none is given a new one will be created.
38
+ def initialize(client:, index_names:, batch_size: 100, logger: nil)
39
+ @logger = logger || Logging.logger[self]
40
+
41
+ @client = client
42
+ @index_names = index_names
43
+ @batch_size = batch_size
44
+
45
+ @batch = []
46
+ end
47
+
48
+ # Pushes a record into the index. (This does not send the record to the
49
+ # Elasticsearch instance, only puts it into the send queue).
50
+ # @param [Hash] data The data to be pushed to the index.
51
+ def push(data)
52
+ index_names.each do |index_name|
53
+ batch << { index: { _index: index_name, _type: 'nested', data: data } }
54
+ end
55
+
56
+ flush! if batch.size >= batch_size
57
+ end
58
+
59
+ # Sends a record to the Elasticsearch instance right away.
60
+ # @param [Hash] data The data to be sent.
61
+ # @param [String, nil] type The type of the document. When set to +nil+
62
+ # the decision is left to Elasticsearch's API. Which will normally
63
+ # default to +_doc+.
64
+ # @return [Array<Hash>] An array with hashes containing information about
65
+ # the created documents. An example of such Hashes is:
66
+ #
67
+ # {
68
+ # "_index" => "xyz01_unit_test",
69
+ # "_type" => "nested",
70
+ # "_id" => "SVY1mJEBQ5CNFZM8Lodt",
71
+ # "_version" => 1,
72
+ # "result" => "created",
73
+ # "_shards" => { "total" => 2, "successful" => 1, "failed" => 0 },
74
+ # "_seq_no" => 0,
75
+ # "_primary_term" => 1
76
+ # }
77
+ #
78
+ # For information on the contents of this Hash please see:
79
+ # https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-index_.html#docs-index-api-response-body
80
+ def index(data, type: DEFAULT_DOC_TYPE)
81
+ raise ArgumentError, "Unsupported type: '#{type}'" unless SUPPORTED_TYPES.include?(type)
82
+
83
+ index_names.map { |index_name| client.index index: index_name, type: type, body: data }
84
+ end
85
+
86
+ # Performs a query on the index.
87
+ # For more information on how to build the query please refer to the
88
+ # Elasticsearch DSL query:
89
+ # https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl.html
90
+ # @param [Hash] query The query to perform.
91
+ # @param [JayAPI::Elasticsearch::BatchCounter, nil] batch_counter Object keeping track of batches.
92
+ # @param [Symbol, nil] type Type of query, at the moment either nil or :search_after.
93
+ # @return [JayAPI::Elasticsearch::QueryResults] The query results.
94
+ # @raise [Elasticsearch::Transport::Transport::ServerError] If the
95
+ # query fails.
96
+ def search(query, batch_counter: nil, type: nil)
97
+ begin
98
+ response = Response.new(client.search(index: index_names, body: query))
99
+ rescue ::Elasticsearch::Transport::Transport::Errors::BadRequest
100
+ logger.error "The 'search' query is invalid: #{JSON.pretty_generate(query)}"
101
+ raise
102
+ end
103
+ query_results(query, response, batch_counter, type)
104
+ end
105
+
106
+ # Sends whatever is currently in the send queue to the Elasticsearch
107
+ # instance and clears the queue.
108
+ def flush
109
+ return unless @batch.any?
110
+
111
+ flush!
112
+ end
113
+
114
+ # Returns the number of elements currently on the send queue.
115
+ # @return [Integer] The number of items in the send queue.
116
+ def queue_size
117
+ batch.size
118
+ end
119
+
120
+ # Delete the documents matching the given query from the Index.
121
+ # For more information on how to build the query please refer to the
122
+ # Elasticsearch DSL documentation:
123
+ # https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl.html
124
+ # https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-delete-by-query.html
125
+ # @param [Hash] query The delete query
126
+ # @param [Integer] slices Number of slices to cut the operation into for
127
+ # faster processing (i.e., run the operation in parallel)
128
+ # @param [Boolean] wait_for_completion False if Elasticsearch should not
129
+ # wait for completion and perform the request asynchronously, true if it
130
+ # should wait for completion (i.e., run the operation synchronously)
131
+ # @return [Hash] A Hash that details the results of the operation
132
+ # @example Returned Hash (with `wait_for_completion: true`):
133
+ # {
134
+ # took: 103,
135
+ # timed_out: false,
136
+ # total: 76,
137
+ # deleted: 76,
138
+ # batches: 1,
139
+ # version_conflicts: 0,
140
+ # noops: 0,
141
+ # retries: { bulk: 0, search: 0 },
142
+ # throttled_millis: 0,
143
+ # requests_per_second: 1.0,
144
+ # throttled_until_millis: 0,
145
+ # failures: []
146
+ # }
147
+ # @example Returned Hash (with `wait_for_completion: false`):
148
+ # {
149
+ # task: "B5oDyEsHQu2Q-wpbaMSMTg:577388264"
150
+ # }
151
+ # @raise [Elasticsearch::Transport::Transport::ServerError] If the
152
+ # query fails.
153
+ def delete_by_query(query, slices: nil, wait_for_completion: true)
154
+ request_params = { index: index_names, body: query }.tap do |params|
155
+ params.merge!(slices: slices) if slices
156
+ params.merge!(wait_for_completion: false) unless wait_for_completion
157
+ end
158
+
159
+ client.delete_by_query(**request_params).deep_symbolize_keys
160
+ end
161
+
162
+ # Deletes asynchronously the documents matching the given query from the
163
+ # Index.
164
+ # For more information on how to build the query please refer to the
165
+ # Elasticsearch DSL documentation:
166
+ # https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl.html
167
+ # https://www.elastic.co/guide/en/elasticsearch/reference/current/docs-delete-by-query.html
168
+ # @param [Hash] query The delete query
169
+ # @param [Integer, String] slices Number of slices to cut the operation
170
+ # into for faster processing (i.e., run the operation in parallel). Use
171
+ # "auto" to make Elasticsearch decide how many slices to divide into
172
+ # @return [Concurrent::Promise] The eventual value returned from the single
173
+ # completion of the delete operation
174
+ def delete_by_query_async(query, slices: nil)
175
+ async.delete_by_query(query, slices: slices)
176
+ end
177
+
178
+ private
179
+
180
+ attr_reader :index_names, :logger, :batch
181
+
182
+ # Scans the Elasticsearch response in search for the first item that has
183
+ # an erroneous state and raises an error including the error details.
184
+ # @param [Hash] response The response returned by the Elasticsearch client.
185
+ # @raise [Errors::ElasticsearchError] Is always raised.
186
+ def handle_errors(response)
187
+ error_item = response['items'].find { |item| item['index']['error'] }
188
+
189
+ raise Errors::ElasticsearchError,
190
+ "An error occurred when pushing the data to Elasticsearch:\n#{error_item['index']['error'].inspect}"
191
+ end
192
+
193
+ # Flushes the current send queue to the Elasticsearch instance and
194
+ # clears the queue.
195
+ def flush!
196
+ logger.info "Pushing data to Elasticsearch (#{batch.size} records)..."
197
+ response = client.bulk body: batch
198
+
199
+ handle_errors(response) if response['errors']
200
+
201
+ logger.info 'Done'
202
+ @batch = []
203
+ end
204
+
205
+ # @param [Hash] query The elastic search query.
206
+ # @param [JayAPI::Elasticsearch::Response] response The response to the query.
207
+ # @param [JayAPI::Elasticsearch::BatchCounter, nil] batch_counter Object keeping track of batches.
208
+ # @param [Symbol, nil] type Type of query, at the moment either nil or :search_after.
209
+ # @return [QueryResults]
210
+ def query_results(query, response, batch_counter, type)
211
+ (type == :search_after ? SearchAfterResults : QueryResults).new(
212
+ index: self,
213
+ query: query,
214
+ response: response,
215
+ batch_counter: BatchCounter.create_or_update(batch_counter, query, response.size)
216
+ )
217
+ end
218
+
219
+ # @return [JayAPI::Elasticsearch::Async]
220
+ def async
221
+ @async ||= JayAPI::Elasticsearch::Async.new(self)
222
+ end
223
+ end
224
+ end
225
+ end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'indexable'
4
+
5
+ module JayAPI
6
+ module Elasticsearch
7
+ # Represents a group of Elasticsearch indexes. Allows the execution of
8
+ # searches over all of the specified indexes or push data to all of them
9
+ # at the same time.
10
+ class Indexes
11
+ include ::JayAPI::Elasticsearch::Indexable
12
+
13
+ # @param [JayAPI::Elasticsearch::Client] client The Elasticsearch Client object.
14
+ # @param [Array<String>] index_names The names of the Elasticsearch indexes.
15
+ # @param [Integer] batch_size The size of the batch. When this many items
16
+ # are pushed into the indexes they are flushed to the Elasticsearch
17
+ # instance.
18
+ # @param [Logging::Logger, nil] logger The logger object to use, if
19
+ # none is given a new one will be created.
20
+ def initialize(client:, index_names:, batch_size: 100, logger: nil)
21
+ super
22
+
23
+ return if (batch_size % index_names.size).zero?
24
+
25
+ self.logger.warn(
26
+ "'batch_size' is not a multiple of the number of elements in 'index_names'. " \
27
+ "This can lead to a _bulk size slightly bigger than 'batch_size'"
28
+ )
29
+ end
30
+
31
+ attr_reader :index_names
32
+ end
33
+ end
34
+ end
@@ -21,8 +21,8 @@ module JayAPI
21
21
  def_delegators :response, :hits, :total, :size, :count, :first, :last, :any?, :empty?, :aggregations
22
22
 
23
23
  # Creates a new instance of the class.
24
- # @param [JayAPI::Elasticsearch::Index] index The Elasticsearch
25
- # index used to perform the query.
24
+ # @param [JayAPI::Elasticsearch::Indexable] index The Elasticsearch
25
+ # index or indexes over which the query should be performed.
26
26
  # @param [Hash] query The query that produced the results.
27
27
  # @param [JayAPI::Elasticsearch::Results] response An object containing Docs retrieved from Elasticsearch.
28
28
  # @param [JayAPI::Elasticsearch::BatchCounter] batch_counter An object keeping track of the current batch.
@@ -6,6 +6,7 @@ require_relative 'elasticsearch/client'
6
6
  require_relative 'elasticsearch/client_factory'
7
7
  require_relative 'elasticsearch/errors'
8
8
  require_relative 'elasticsearch/index'
9
+ require_relative 'elasticsearch/indexes'
9
10
  require_relative 'elasticsearch/query_builder'
10
11
  require_relative 'elasticsearch/query_results'
11
12
  require_relative 'elasticsearch/response'
@@ -2,5 +2,5 @@
2
2
 
3
3
  module JayAPI
4
4
  # JayAPI gem's semantic version
5
- VERSION = '28.3.0'
5
+ VERSION = '28.4.0'
6
6
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: jay_api
3
3
  version: !ruby/object:Gem::Version
4
- version: 28.3.0
4
+ version: 28.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Accenture-Industry X
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2025-06-05 00:00:00.000000000 Z
12
+ date: 2025-08-26 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
@@ -135,6 +135,8 @@ files:
135
135
  - lib/jay_api/elasticsearch/errors/query_execution_timeout.rb
136
136
  - lib/jay_api/elasticsearch/errors/search_after_error.rb
137
137
  - lib/jay_api/elasticsearch/index.rb
138
+ - lib/jay_api/elasticsearch/indexable.rb
139
+ - lib/jay_api/elasticsearch/indexes.rb
138
140
  - lib/jay_api/elasticsearch/query_builder.rb
139
141
  - lib/jay_api/elasticsearch/query_builder/aggregations.rb
140
142
  - lib/jay_api/elasticsearch/query_builder/aggregations/aggregation.rb