Class: ElasticGraph::GraphQL::Aggregation::AggregationDetail

Inherits:
Data
  • Object
show all
Defined in:
lib/elastic_graph/graphql/aggregation/query.rb

Overview

The details of an aggregation level, including the ‘aggs` clauses themselves and `meta` that we want echoed back to us in the response for the aggregation level.

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#clausesObject (readonly)

Returns the value of attribute clauses

Returns:

  • (Object)

    the current value of clauses



133
134
135
# File 'lib/elastic_graph/graphql/aggregation/query.rb', line 133

def clauses
  @clauses
end

#metaObject (readonly)

Returns the value of attribute meta

Returns:

  • (Object)

    the current value of meta



133
134
135
# File 'lib/elastic_graph/graphql/aggregation/query.rb', line 133

def meta
  @meta
end

Instance Method Details

#wrap_with_grouping(grouping, query:) ⇒ Object

Wraps this aggregation detail in another aggregation layer for the given ‘grouping`, so that we can easily build up the necessary multi-level aggregation structure.



144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
# File 'lib/elastic_graph/graphql/aggregation/query.rb', line 144

def wrap_with_grouping(grouping, query:)
  agg_key = grouping.key
  extra_inner_meta = grouping.inner_meta.merge({
    # The response just includes tuples of values for the key of each bucket. We need to know what fields those
    # values come from, and this `meta` field  indicates that.
    "grouping_fields" => [agg_key]
  })

  inner_agg_hash = {
    "aggs" => (clauses unless (clauses || {}).empty?),
    "meta" => meta.merge(extra_inner_meta)
  }.compact

  wrapped_clauses = {
    agg_key => grouping.non_composite_clause_for(query).merge(inner_agg_hash)
  }

  unless grouping.handles_missing_values?
    # Here we include a `missing` aggregation as a sibling to the main grouping aggregation. We do this
    # so that we get a bucket of documents that have `null` values for the field we are grouping on, in
    # order to provide the same behavior as the `CompositeGroupingAdapter` (which uses the built-in
    # `missing_bucket` option).
    #
    # To work correctly, we need to include this `missing` aggregation as a sibling at _every_ level of
    # the aggregation structure, and the `missing` aggregation needs the same child aggregations as the
    # main grouping aggregation has. Given the recursive nature of how this is applied, this results in
    # a fairly complex structure, even though conceptually the idea behind this isn't _too_ bad.
    missing_bucket_inner_agg_hash = inner_agg_hash.key?("aggs") ? inner_agg_hash : {} # : ::Hash[::String, untyped]
    missing_bucket_inner_agg_hash = missing_bucket_inner_agg_hash.merge({
      "missing" => {"field" => grouping.encoded_index_field_path}
    })
    wrapped_clauses = wrapped_clauses.merge({
      Key.missing_value_bucket_key(agg_key) => missing_bucket_inner_agg_hash
    })
  end

  AggregationDetail.new(wrapped_clauses, {"buckets_path" => [agg_key]})
end