jay_api 28.1.0 → 28.3.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: 0b2d35c2ed340724fe54f7f099ed3fb5f200249c72604b906a39ecdef13be6fb
4
- data.tar.gz: 4da5c5a7dca36ea23ca6241ac5f44846558d620a60ce9382dff422ca3575f4fe
3
+ metadata.gz: 07ffb602dd7c52159b2142a00f06401d0326ae8e82e05ba24c61f96d35347d8c
4
+ data.tar.gz: 7f0f39ca31de378467d2914e3322fd83f6fad7a0b2185a30c94582d213d04439
5
5
  SHA512:
6
- metadata.gz: 74414baf82a02115568311cfce173e990c3777da5d3a18eed084366048968f88c1a42e581a2652544cc9952ff1e32b135528c622cd2d30554a429c952b544aa2
7
- data.tar.gz: 5bbe6985eb4d5b3bd1263f1ebd6d23f83afb2a9b5eb48bce31a710628bdd35f6051c0b643bcdaab8c22ffc977b90e4bd79e3b94468a9d8b0b0984065408df92a
6
+ metadata.gz: 8bc9fc4c9631aac5a504600ccabd68ff875e7027682f83b47830608a6578cc7a73702333be180b4dd9c7b5d9d637c32b1ef6d86a6519ba5ef8a40706b0a5d397
7
+ data.tar.gz: 290b96e8925ee9bbff77e469bdd8299291317639dfd37ea345e1fb88e608c45b1d799015dd6d94592a300e24a97d1aab34df7de4a3ebb8c7ef014b4a09b2e2ed
data/CHANGELOG.md CHANGED
@@ -8,6 +8,18 @@ Please mark backwards incompatible changes with an exclamation mark at the start
8
8
 
9
9
  ## [Unreleased]
10
10
 
11
+ ## [28.3.0] - 2025-06-05
12
+
13
+ ### Added
14
+ - The `Aggregations::Composite` class and the `Aggregations#composite` method.
15
+ They make it possible to use Elasticsearch's `composite` aggregations.
16
+
17
+ ## [28.2.0] - 2025-05-30
18
+
19
+ ### Added
20
+ - The `#nodes` method to the `Elasticsearch::Stats` class. This method gives the
21
+ user access to the node-related statistics of the Elasticsearch cluster.
22
+
11
23
  ## [28.1.0] - 2025-05-19
12
24
 
13
25
  ### Added
@@ -0,0 +1,77 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support'
4
+ require 'active_support/core_ext/string/inflections'
5
+
6
+ require_relative 'aggregation'
7
+ require_relative 'sources/sources'
8
+ require_relative 'errors/aggregations_error'
9
+
10
+ module JayAPI
11
+ module Elasticsearch
12
+ class QueryBuilder
13
+ class Aggregations
14
+ # Represents a Composite aggregation in Elasticsearch. For more
15
+ # information about this type of aggregation:
16
+ # @see https://www.elastic.co/docs/reference/aggregations/search-aggregations-bucket-composite-aggregation
17
+ class Composite < ::JayAPI::Elasticsearch::QueryBuilder::Aggregations::Aggregation
18
+ attr_reader :size
19
+
20
+ # @param [String] name The name of the composite aggregation.
21
+ # @param [Integer] size The number of composite buckets to return.
22
+ # @yieldparam [JayAPI::Elasticsearch::QueryBuilder::Aggregations::Sources::Sources]
23
+ # The collection of sources for the composite aggregation. This
24
+ # should be used by the caller to add sources to the composite
25
+ # aggregation.
26
+ # @raise [JayAPI::Elasticsearch::QueryBuilder::Aggregations::Errors::AggregationsError]
27
+ # If the method is called without a block.
28
+ def initialize(name, size: nil, &block)
29
+ unless block
30
+ raise(::JayAPI::Elasticsearch::QueryBuilder::Aggregations::Errors::AggregationsError,
31
+ "The #{self.class.name.demodulize} aggregation must be initialized with a block")
32
+ end
33
+
34
+ super(name)
35
+ @size = size
36
+ block.call(sources)
37
+ end
38
+
39
+ # @return [self] A copy of the receiver. Sources and nested
40
+ # aggregations are also cloned.
41
+ def clone
42
+ # rubocop:disable Lint/EmptyBlock (The sources will be assigned later)
43
+ copy = self.class.new(name, size: size) {}
44
+ # rubocop:enable Lint/EmptyBlock
45
+
46
+ copy.aggregations = aggregations.clone
47
+ copy.sources = sources.clone
48
+ copy
49
+ end
50
+
51
+ # @return [Hash] The Hash representation of the +Aggregation+.
52
+ # Properly formatted for Elasticsearch.
53
+ def to_h
54
+ super do
55
+ {
56
+ composite: {
57
+ sources: sources.to_a,
58
+ size: size
59
+ }.compact
60
+ }
61
+ end
62
+ end
63
+
64
+ protected
65
+
66
+ attr_writer :sources # Used by the #clone method
67
+
68
+ # @return [JayAPI::Elasticsearch::QueryBuilder::Aggregations::Sources::Sources]
69
+ # The collection of sources of the composite aggregation.
70
+ def sources
71
+ @sources ||= ::JayAPI::Elasticsearch::QueryBuilder::Aggregations::Sources::Sources.new
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'terms'
4
+
5
+ module JayAPI
6
+ module Elasticsearch
7
+ class QueryBuilder
8
+ class Aggregations
9
+ module Sources
10
+ # Represents the collection of sources for a Composite aggregation in
11
+ # Elasticsearch
12
+ class Sources
13
+ # Adds a +terms+ source to the collection.
14
+ # For information about the parameters:
15
+ # @see Sources::Terms#initialize
16
+ def terms(name, **kw_args)
17
+ sources.push(::JayAPI::Elasticsearch::QueryBuilder::Aggregations::Sources::Terms.new(name, **kw_args))
18
+ end
19
+
20
+ # @return [Array<Hash>] Array representation of the collection of
21
+ # sources of the composite aggregation.
22
+ def to_a
23
+ sources.map(&:to_h)
24
+ end
25
+
26
+ # @return [self] A copy of the receiver (not a shallow clone, it
27
+ # clones all of the elements of the collection).
28
+ def clone
29
+ self.class.new.tap do |copy|
30
+ copy.sources.concat(sources.map(&:clone))
31
+ end
32
+ end
33
+
34
+ protected
35
+
36
+ # @return [Array<Object>] The array used to hold the collection of
37
+ # sources.
38
+ def sources
39
+ @sources ||= []
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ module JayAPI
4
+ module Elasticsearch
5
+ class QueryBuilder
6
+ class Aggregations
7
+ module Sources
8
+ # Represents a "Terms" value source for a Composite aggregation.
9
+ # More information about this type of value source can be found here:
10
+ # https://www.elastic.co/docs/reference/aggregations/search-aggregations-bucket-composite-aggregation#_terms
11
+ class Terms
12
+ attr_reader :name, :field, :order, :missing_bucket, :missing_order
13
+
14
+ # @param [String] name The name for the value source.
15
+ # @param [String] field The field for the value source.
16
+ # @param [String, nil] order The order in which the values coming
17
+ # from this data source should be ordered, this can be either
18
+ # "asc" or "desc"
19
+ # @param [Boolean] missing_bucket Whether or not a bucket for the
20
+ # documents without a value in +field+ should be created.
21
+ # @param [String] missing_order Where to put the bucket for the
22
+ # documents with a missing value, either "first" or "last".
23
+ def initialize(name, field:, order: nil, missing_bucket: nil, missing_order: nil)
24
+ @name = name
25
+ @field = field
26
+ @order = order
27
+ @missing_bucket = missing_bucket
28
+ @missing_order = missing_order
29
+ end
30
+
31
+ # @return [self] A copy of the receiver.
32
+ def clone
33
+ self.class.new(
34
+ name, field: field, order: order, missing_bucket: missing_bucket, missing_order: missing_order
35
+ )
36
+ end
37
+
38
+ # @return [Hash] The hash representation for the value source.
39
+ def to_h
40
+ {
41
+ name => {
42
+ terms: {
43
+ field: field,
44
+ order: order,
45
+ missing_bucket: missing_bucket,
46
+ missing_order: missing_order
47
+ }.compact
48
+ }
49
+ }
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -5,6 +5,7 @@ require 'forwardable'
5
5
  require_relative 'aggregations/aggregation'
6
6
  require_relative 'aggregations/avg'
7
7
  require_relative 'aggregations/cardinality'
8
+ require_relative 'aggregations/composite'
8
9
  require_relative 'aggregations/date_histogram'
9
10
  require_relative 'aggregations/filter'
10
11
  require_relative 'aggregations/scripted_metric'
@@ -121,6 +122,16 @@ module JayAPI
121
122
  )
122
123
  end
123
124
 
125
+ # Adds a +composite+ aggregation. For more information about the parameters:
126
+ # @see JayAPI::Elasticsearch::QueryBuilder::Aggregations::Composite#initialize
127
+ def composite(name, size: nil, &block)
128
+ add(
129
+ ::JayAPI::Elasticsearch::QueryBuilder::Aggregations::Composite.new(
130
+ name, size: size, &block
131
+ )
132
+ )
133
+ end
134
+
124
135
  # Returns a Hash with the correct format for the current list of
125
136
  # aggregations. For example:
126
137
  #
@@ -0,0 +1,15 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../../../errors/error'
4
+
5
+ module JayAPI
6
+ module Elasticsearch
7
+ class Stats
8
+ module Errors
9
+ # An error to be raised when a particular Stats element is requested for
10
+ # which there is no data in the response received from the cluster.
11
+ class StatsDataNotAvailable < ::JayAPI::Errors::Error; end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ module JayAPI
4
+ module Elasticsearch
5
+ class Stats
6
+ class Node
7
+ # Holds storage information related to one of the nodes in the
8
+ # Elasticsearch cluster.
9
+ class Storage
10
+ TOTAL_KEY = 'total_in_bytes'
11
+ FREE_KEY = 'free_in_bytes'
12
+ AVAILABLE_KEY = 'available_in_bytes'
13
+
14
+ # @param [Hash] data Data about the Node's storage.
15
+ def initialize(data)
16
+ @data = data
17
+ end
18
+
19
+ # @return [Integer] The total size of the storage (in bytes)
20
+ def total
21
+ @total ||= data[TOTAL_KEY]
22
+ end
23
+
24
+ # @return [Integer] The total number of bytes that are free on the
25
+ # node.
26
+ def free
27
+ @free ||= data[FREE_KEY]
28
+ end
29
+
30
+ # @return [Integer] The total number of bytes that are available on
31
+ # the node. In general this is equal to #free, but not always.
32
+ def available
33
+ @available ||= data[AVAILABLE_KEY]
34
+ end
35
+
36
+ # @return [self] A new instance of the class with the added storage of
37
+ # the receiver and +other+.
38
+ def +(other)
39
+ raise ArgumentError, "Cannot add #{self.class} and #{other.class} together" unless other.is_a?(self.class)
40
+
41
+ self.class.new(
42
+ TOTAL_KEY => total + other.total,
43
+ FREE_KEY => free + other.free,
44
+ AVAILABLE_KEY => available + other.available
45
+ )
46
+ end
47
+
48
+ private
49
+
50
+ attr_reader :data
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'errors/stats_data_not_available'
4
+ require_relative 'node/storage'
5
+
6
+ module JayAPI
7
+ module Elasticsearch
8
+ class Stats
9
+ # Holds information about one of the nodes in the Elasticsearch cluster.
10
+ class Node
11
+ attr_reader :name
12
+
13
+ # @param [String] name The name of the node.
14
+ # @param [Hash] data Information about the node.
15
+ def initialize(name, data)
16
+ @name = name
17
+ @data = data
18
+ end
19
+
20
+ # @return [JayAPI::Elasticsearch::Stats::Node::Storage] Storage
21
+ # information about the node.
22
+ # @raise [JayAPI::Elasticsearch::Stats::Errors::StatsDataNotAvailable]
23
+ # If there is no storage information for the node.
24
+ def storage
25
+ @storage ||= ::JayAPI::Elasticsearch::Stats::Node::Storage.new(fs_totals)
26
+ end
27
+
28
+ private
29
+
30
+ attr_reader :data
31
+
32
+ # @return [Hash] Aggregated information about the +Node+'s
33
+ # filesystem.
34
+ # @raise [JayAPI::Elasticsearch::Stats::Errors::StatsDataNotAvailable]
35
+ # If there is no filesystem information for the node.
36
+ def fs_totals
37
+ @fs_totals ||= data.dig('fs', 'total') || raise(
38
+ ::JayAPI::Elasticsearch::Stats::Errors::StatsDataNotAvailable,
39
+ "Filesystem data not available for node #{name}"
40
+ )
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'forwardable'
4
+
5
+ require_relative 'node'
6
+
7
+ module JayAPI
8
+ module Elasticsearch
9
+ class Stats
10
+ # Provides access to the list of nodes returned by Elasticsearch's Stats API
11
+ class Nodes
12
+ extend Forwardable
13
+
14
+ def_delegator :nodes, :size
15
+
16
+ # @param [Hash] nodes Information about the nodes in the Elasticsearch
17
+ # cluster.
18
+ def initialize(nodes)
19
+ @nodes = nodes
20
+ end
21
+
22
+ # @return [Enumerator::Lazy<JayAPI::Elasticsearch::Stats::Node>] A lazy
23
+ # enumerator of +Node+ objects, one for each of the nodes.
24
+ def all
25
+ @all ||= with_lazy_instantiation { nodes }
26
+ end
27
+
28
+ private
29
+
30
+ attr_reader :nodes
31
+
32
+ def build_node(args)
33
+ ::JayAPI::Elasticsearch::Stats::Node.new(*args)
34
+ end
35
+
36
+ # Calls the given block and turns its return value into a lazy
37
+ # enumerator that instantiates a +Node+ object for each of the
38
+ # elements of the collection returned by the block.
39
+ # @return [Enumerator::Lazy<JayAPI::Elasticsearch::Stats::Node>]
40
+ def with_lazy_instantiation(&block)
41
+ block.call.lazy.map(&method(:build_node))
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -2,6 +2,8 @@
2
2
 
3
3
  require_relative 'stats/index'
4
4
  require_relative 'stats/indices'
5
+ require_relative 'stats/node'
6
+ require_relative 'stats/nodes'
5
7
 
6
8
  module JayAPI
7
9
  module Elasticsearch
@@ -21,19 +23,37 @@ module JayAPI
21
23
  # to the Statistics API endpoint fails.
22
24
  def indices
23
25
  # DO NOT MEMOIZE! Leave it to the caller.
24
- ::JayAPI::Elasticsearch::Stats::Indices.new(response['indices'])
26
+ ::JayAPI::Elasticsearch::Stats::Indices.new(indices_stats['indices'])
27
+ end
28
+
29
+ # @return [JayAPI::Elasticsearch::Stats::Nodes] Information about the
30
+ # nodes that make up the Elasticsearch cluster.
31
+ # @raise [Elasticsearch::Transport::Transport::ServerError] If the request
32
+ # to the Statistics API endpoint fails.
33
+ def nodes
34
+ # DO NOT MEMOIZE! Leave it to the caller.
35
+ ::JayAPI::Elasticsearch::Stats::Nodes.new(nodes_stats['nodes'])
25
36
  end
26
37
 
27
38
  private
28
39
 
29
- # @return [Hash] The Hash with the statistics returned by the
30
- # Elasticsearch cluster.
40
+ # @return [Hash] The Hash with the index-related statistics returned by
41
+ # the Elasticsearch cluster.
31
42
  # @raise [Elasticsearch::Transport::Transport::ServerError] If the
32
43
  # request fails.
33
- def response
44
+ def indices_stats
34
45
  # DO NOT MEMOIZE! Leave it to the caller.
35
46
  transport_client.indices.stats
36
47
  end
48
+
49
+ # @return [Hash] The Hash with the node-related statistics returned by the
50
+ # Elasticsearch cluster.
51
+ # @raise [Elasticsearch::Transport::Transport::ServerError] If the
52
+ # request fails.
53
+ def nodes_stats
54
+ # DO NOT MEMOIZE! Leave it to the caller.
55
+ transport_client.nodes.stats
56
+ end
37
57
  end
38
58
  end
39
59
  end
@@ -2,5 +2,5 @@
2
2
 
3
3
  module JayAPI
4
4
  # JayAPI gem's semantic version
5
- VERSION = '28.1.0'
5
+ VERSION = '28.3.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.1.0
4
+ version: 28.3.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-05-19 00:00:00.000000000 Z
12
+ date: 2025-06-05 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
@@ -140,12 +140,15 @@ files:
140
140
  - lib/jay_api/elasticsearch/query_builder/aggregations/aggregation.rb
141
141
  - lib/jay_api/elasticsearch/query_builder/aggregations/avg.rb
142
142
  - lib/jay_api/elasticsearch/query_builder/aggregations/cardinality.rb
143
+ - lib/jay_api/elasticsearch/query_builder/aggregations/composite.rb
143
144
  - lib/jay_api/elasticsearch/query_builder/aggregations/date_histogram.rb
144
145
  - lib/jay_api/elasticsearch/query_builder/aggregations/errors.rb
145
146
  - lib/jay_api/elasticsearch/query_builder/aggregations/errors/aggregations_error.rb
146
147
  - lib/jay_api/elasticsearch/query_builder/aggregations/filter.rb
147
148
  - lib/jay_api/elasticsearch/query_builder/aggregations/max.rb
148
149
  - lib/jay_api/elasticsearch/query_builder/aggregations/scripted_metric.rb
150
+ - lib/jay_api/elasticsearch/query_builder/aggregations/sources/sources.rb
151
+ - lib/jay_api/elasticsearch/query_builder/aggregations/sources/terms.rb
149
152
  - lib/jay_api/elasticsearch/query_builder/aggregations/sum.rb
150
153
  - lib/jay_api/elasticsearch/query_builder/aggregations/terms.rb
151
154
  - lib/jay_api/elasticsearch/query_builder/aggregations/top_hits.rb
@@ -172,8 +175,12 @@ files:
172
175
  - lib/jay_api/elasticsearch/response.rb
173
176
  - lib/jay_api/elasticsearch/search_after_results.rb
174
177
  - lib/jay_api/elasticsearch/stats.rb
178
+ - lib/jay_api/elasticsearch/stats/errors/stats_data_not_available.rb
175
179
  - lib/jay_api/elasticsearch/stats/index.rb
176
180
  - lib/jay_api/elasticsearch/stats/indices.rb
181
+ - lib/jay_api/elasticsearch/stats/node.rb
182
+ - lib/jay_api/elasticsearch/stats/node/storage.rb
183
+ - lib/jay_api/elasticsearch/stats/nodes.rb
177
184
  - lib/jay_api/elasticsearch/tasks.rb
178
185
  - lib/jay_api/elasticsearch/time.rb
179
186
  - lib/jay_api/errors/configuration_error.rb