Module: ParadeDB::Aggregations

Defined in:
lib/parade_db/aggregations.rb

Overview

Typed helpers for building agg JSON payloads passed to pdb.agg(...).

Defined Under Namespace

Classes: FieldTermFilter, FilteredSpec

Constant Summary collapse

TERMS_ORDER =
{
  count_desc: { "_count" => "desc" },
  count_asc: { "_count" => "asc" },
  key_desc: { "_key" => "desc" },
  key_asc: { "_key" => "asc" }
}.freeze

Class Method Summary collapse

Class Method Details

.avg(field) ⇒ Object



43
44
45
# File 'lib/parade_db/aggregations.rb', line 43

def avg(field)
  metric("avg", field)
end

.build_named_payload(named_aggregations) ⇒ Object

Raises:

  • (ArgumentError)


21
22
23
24
25
26
27
28
29
# File 'lib/parade_db/aggregations.rb', line 21

def build_named_payload(named_aggregations)
  specs = named_aggregations.to_h
  raise ArgumentError, "with_agg/facets_agg requires at least one named aggregation" if specs.empty?

  specs.each_with_object({}) do |(alias_name, spec), payload|
    alias_key = normalize_alias(alias_name)
    payload[alias_key] = normalize_named_spec(spec)
  end
end

.date_histogram(field, calendar_interval: nil, fixed_interval: nil, interval: nil, min_doc_count: nil, offset: nil, time_zone: nil, format: nil, hard_bounds: nil, extended_bounds: nil) ⇒ Object



84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/parade_db/aggregations.rb', line 84

def date_histogram(
  field,
  calendar_interval: nil,
  fixed_interval: nil,
  interval: nil,
  min_doc_count: nil,
  offset: nil,
  time_zone: nil,
  format: nil,
  hard_bounds: nil,
  extended_bounds: nil
)
  interval_args = {
    "calendar_interval" => calendar_interval,
    "fixed_interval" => fixed_interval,
    "interval" => interval
  }.compact

  if interval_args.empty?
    raise ArgumentError, "date_histogram requires one of: calendar_interval, fixed_interval, interval"
  end

  if interval_args.length > 1
    raise ArgumentError, "date_histogram interval arguments are mutually exclusive"
  end

  payload = { "field" => normalize_field(field) }.merge(interval_args)
  payload["min_doc_count"] = normalize_non_negative_integer(min_doc_count, "min_doc_count") unless min_doc_count.nil?
  payload["offset"] = offset unless offset.nil?
  payload["time_zone"] = time_zone unless time_zone.nil?
  payload["format"] = format unless format.nil?
  payload["hard_bounds"] = normalize_bounds(hard_bounds, "hard_bounds") unless hard_bounds.nil?
  payload["extended_bounds"] = normalize_bounds(extended_bounds, "extended_bounds") unless extended_bounds.nil?
  { "date_histogram" => payload }
end

.filtered(spec, filter: nil, field: nil, term: nil) ⇒ Object



150
151
152
153
154
# File 'lib/parade_db/aggregations.rb', line 150

def filtered(spec, filter: nil, field: nil, term: nil)
  normalized_spec = normalize_spec(spec)
  normalized_filter = normalize_filter(filter: filter, field: field, term: term)
  FilteredSpec.new(spec: normalized_spec, agg_filter: normalized_filter)
end

.histogram(field, interval:, min_doc_count: nil, offset: nil, hard_bounds: nil, extended_bounds: nil) ⇒ Object

Raises:

  • (ArgumentError)


70
71
72
73
74
75
76
77
78
79
80
81
82
# File 'lib/parade_db/aggregations.rb', line 70

def histogram(field, interval:, min_doc_count: nil, offset: nil, hard_bounds: nil, extended_bounds: nil)
  raise ArgumentError, "interval is required" if interval.nil?

  payload = {
    "field" => normalize_field(field),
    "interval" => interval
  }
  payload["min_doc_count"] = normalize_non_negative_integer(min_doc_count, "min_doc_count") unless min_doc_count.nil?
  payload["offset"] = offset unless offset.nil?
  payload["hard_bounds"] = normalize_bounds(hard_bounds, "hard_bounds") unless hard_bounds.nil?
  payload["extended_bounds"] = normalize_bounds(extended_bounds, "extended_bounds") unless extended_bounds.nil?
  { "histogram" => payload }
end

.max(field) ⇒ Object



55
56
57
# File 'lib/parade_db/aggregations.rb', line 55

def max(field)
  metric("max", field)
end

.min(field) ⇒ Object



51
52
53
# File 'lib/parade_db/aggregations.rb', line 51

def min(field)
  metric("min", field)
end

.percentiles(field, percents:) ⇒ Object

Raises:

  • (ArgumentError)


63
64
65
66
67
68
# File 'lib/parade_db/aggregations.rb', line 63

def percentiles(field, percents:)
  values = Array(percents)
  raise ArgumentError, "percents must include at least one value" if values.empty?

  { "percentiles" => { "field" => normalize_field(field), "percents" => values } }
end

.range(field, ranges:) ⇒ Object

Raises:

  • (ArgumentError)


120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
# File 'lib/parade_db/aggregations.rb', line 120

def range(field, ranges:)
  serialized_ranges = Array(ranges).map do |entry|
    raise ArgumentError, "range entries must be Hash values" unless entry.is_a?(Hash)

    normalized = deep_stringify(entry)
    unless normalized.key?("from") || normalized.key?("to")
      raise ArgumentError, "range entries require at least one of: from, to"
    end

    normalized
  end
  raise ArgumentError, "ranges must include at least one entry" if serialized_ranges.empty?

  {
    "range" => {
      "field" => normalize_field(field),
      "ranges" => serialized_ranges
    }
  }
end

.stats(field) ⇒ Object



59
60
61
# File 'lib/parade_db/aggregations.rb', line 59

def stats(field)
  metric("stats", field)
end

.sum(field) ⇒ Object



47
48
49
# File 'lib/parade_db/aggregations.rb', line 47

def sum(field)
  metric("sum", field)
end

.terms(field, size: 10, order: :count_desc, missing: nil) ⇒ Object



31
32
33
34
35
36
37
# File 'lib/parade_db/aggregations.rb', line 31

def terms(field, size: 10, order: :count_desc, missing: nil)
  terms_payload = { "field" => normalize_field(field) }
  terms_payload["size"] = normalize_non_negative_integer(size, "size") unless size.nil?
  terms_payload["order"] = normalize_terms_order(order) unless order.nil?
  terms_payload["missing"] = missing unless missing.nil?
  { "terms" => terms_payload }
end

.top_hits(size: nil, from: nil, sort: nil, docvalue_fields: nil) ⇒ Object



141
142
143
144
145
146
147
148
# File 'lib/parade_db/aggregations.rb', line 141

def top_hits(size: nil, from: nil, sort: nil, docvalue_fields: nil)
  payload = {}
  payload["size"] = normalize_non_negative_integer(size, "size") unless size.nil?
  payload["from"] = normalize_non_negative_integer(from, "from") unless from.nil?
  payload["sort"] = normalize_top_hits_sort(sort) unless sort.nil?
  payload["docvalue_fields"] = normalize_docvalue_fields(docvalue_fields) unless docvalue_fields.nil?
  { "top_hits" => payload }
end

.value_count(field) ⇒ Object



39
40
41
# File 'lib/parade_db/aggregations.rb', line 39

def value_count(field)
  metric("value_count", field)
end