Class: Parse::GroupByDate
- Inherits:
-
Object
- Object
- Parse::GroupByDate
- Defined in:
- lib/parse/query.rb
Overview
Helper class for handling group_by_date aggregations with method chaining. Groups data by time intervals (year, month, week, day, hour) and supports aggregation operations.
Direct Known Subclasses
Instance Method Summary collapse
-
#average(field) ⇒ Hash
(also: #avg)
Calculate average of a field for each time period.
-
#count ⇒ Hash
Count the number of items in each time period.
-
#initialize(query, date_field, interval, return_pointers: false, timezone: nil, mongo_direct: false) ⇒ GroupByDate
constructor
A new instance of GroupByDate.
-
#max(field) ⇒ Hash
Find maximum value of a field for each time period.
-
#min(field) ⇒ Hash
Find minimum value of a field for each time period.
-
#order(spec) ⇒ self
Order date-grouped results by the date key or by the aggregated value.
-
#pipeline ⇒ Array<Hash>
Returns the MongoDB aggregation pipeline that would be used for a count operation.
-
#sort(direction = :asc) ⇒ self
Sort date-grouped results by date key (Ruby
Hash#sortdefault). -
#sum(field) ⇒ Hash
Sum a field for each time period.
Constructor Details
#initialize(query, date_field, interval, return_pointers: false, timezone: nil, mongo_direct: false) ⇒ GroupByDate
Returns a new instance of GroupByDate.
7170 7171 7172 7173 7174 7175 7176 7177 7178 7179 |
# File 'lib/parse/query.rb', line 7170 def initialize(query, date_field, interval, return_pointers: false, timezone: nil, mongo_direct: false) @query = query @date_field = date_field @interval = interval @return_pointers = return_pointers @timezone = timezone @mongo_direct = mongo_direct @sort_target = nil # nil | :key | :value (no :size — date groupings have no list accumulator yet) @sort_direction = nil # :asc | :desc end |
Instance Method Details
#average(field) ⇒ Hash Also known as: avg
Calculate average of a field for each time period.
7302 7303 7304 7305 7306 7307 7308 7309 |
# File 'lib/parse/query.rb', line 7302 def average(field) if field.nil? || !field.respond_to?(:to_s) raise ArgumentError, "Invalid field name passed to `average`." end formatted_field = @query.send(:format_aggregation_field, field) execute_date_aggregation("average", { "$avg" => "$#{formatted_field}" }) end |
#count ⇒ Hash
Count the number of items in each time period.
7280 7281 7282 |
# File 'lib/parse/query.rb', line 7280 def count execute_date_aggregation("count", { "$sum" => 1 }) end |
#max(field) ⇒ Hash
Find maximum value of a field for each time period.
7328 7329 7330 7331 7332 7333 7334 7335 |
# File 'lib/parse/query.rb', line 7328 def max(field) if field.nil? || !field.respond_to?(:to_s) raise ArgumentError, "Invalid field name passed to `max`." end formatted_field = @query.send(:format_aggregation_field, field) execute_date_aggregation("max", { "$max" => "$#{formatted_field}" }) end |
#min(field) ⇒ Hash
Find minimum value of a field for each time period.
7316 7317 7318 7319 7320 7321 7322 7323 |
# File 'lib/parse/query.rb', line 7316 def min(field) if field.nil? || !field.respond_to?(:to_s) raise ArgumentError, "Invalid field name passed to `min`." end formatted_field = @query.send(:format_aggregation_field, field) execute_date_aggregation("min", { "$min" => "$#{formatted_field}" }) end |
#order(spec) ⇒ self
Order date-grouped results by the date key or by the aggregated value.
When no ordering is configured the default is chronological by date
(the original behavior). The configured order is pushed into the
pipeline as a $sort stage.
7195 7196 7197 7198 7199 7200 7201 7202 7203 7204 7205 7206 7207 7208 7209 7210 7211 7212 7213 7214 7215 7216 7217 7218 7219 7220 |
# File 'lib/parse/query.rb', line 7195 def order(spec) target, direction = case spec when Symbol [:key, spec] when Hash unless spec.size == 1 raise ArgumentError, "order(...) expects a single pair, e.g. {value: :desc} (got #{spec.inspect})" end k, v = spec.first [k.to_sym, v.to_sym] else raise ArgumentError, "order(...) expects {key:|value: => :asc|:desc} or :asc/:desc (got #{spec.inspect})" end unless %i[key value].include?(target) raise ArgumentError, "order(...) target must be :key or :value for date groupings (got #{target.inspect})" end unless %i[asc desc].include?(direction) raise ArgumentError, "order(...) direction must be :asc or :desc (got #{direction.inspect})" end @sort_target = target @sort_direction = direction self end |
#pipeline ⇒ Array<Hash>
Returns the MongoDB aggregation pipeline that would be used for a count operation. This is useful for debugging and understanding the generated pipeline.
7235 7236 7237 7238 7239 7240 7241 7242 7243 7244 7245 7246 7247 7248 7249 7250 7251 7252 7253 7254 7255 7256 7257 7258 7259 7260 7261 7262 7263 7264 7265 7266 7267 7268 7269 7270 7271 7272 7273 |
# File 'lib/parse/query.rb', line 7235 def pipeline # Format the date field name formatted_date_field = @query.send(:format_aggregation_field, @date_field) # Build the aggregation pipeline (same logic as execute_date_aggregation) pipeline = [] # Add match stage if there are where conditions compiled_where = @query.send(:compile_where) if compiled_where.present? # Convert field names for aggregation context and handle dates aggregation_where = @query.send(:convert_constraints_for_aggregation, compiled_where) stringified_where = @query.send(:convert_dates_for_aggregation, aggregation_where) pipeline << { "$match" => stringified_where } end # Create date grouping expression based on interval using shared method date_expr = build_date_group_expression(formatted_date_field) # Add group, sort, and project stages (using count as example aggregation) pipeline.concat([ { "$group" => { "_id" => date_expr, "count" => { "$sum" => 1 }, }, }, sort_stage, { "$project" => { "_id" => 0, "objectId" => "$_id", "count" => 1, }, }, ]) pipeline end |
#sort(direction = :asc) ⇒ self
Sort date-grouped results by date key (Ruby Hash#sort default).
7225 7226 7227 |
# File 'lib/parse/query.rb', line 7225 def sort(direction = :asc) order(direction) end |
#sum(field) ⇒ Hash
Sum a field for each time period.
7290 7291 7292 7293 7294 7295 7296 7297 |
# File 'lib/parse/query.rb', line 7290 def sum(field) if field.nil? || !field.respond_to?(:to_s) raise ArgumentError, "Invalid field name passed to `sum`." end formatted_field = @query.send(:format_aggregation_field, field) execute_date_aggregation("sum", { "$sum" => "$#{formatted_field}" }) end |