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#sort` default).
-
#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.
6406 6407 6408 6409 6410 6411 6412 6413 6414 6415 |
# File 'lib/parse/query.rb', line 6406 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.
6538 6539 6540 6541 6542 6543 6544 6545 |
# File 'lib/parse/query.rb', line 6538 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.
6516 6517 6518 |
# File 'lib/parse/query.rb', line 6516 def count execute_date_aggregation("count", { "$sum" => 1 }) end |
#max(field) ⇒ Hash
Find maximum value of a field for each time period.
6564 6565 6566 6567 6568 6569 6570 6571 |
# File 'lib/parse/query.rb', line 6564 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.
6552 6553 6554 6555 6556 6557 6558 6559 |
# File 'lib/parse/query.rb', line 6552 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.
6431 6432 6433 6434 6435 6436 6437 6438 6439 6440 6441 6442 6443 6444 6445 6446 6447 6448 6449 6450 6451 6452 6453 6454 6455 6456 |
# File 'lib/parse/query.rb', line 6431 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.
6471 6472 6473 6474 6475 6476 6477 6478 6479 6480 6481 6482 6483 6484 6485 6486 6487 6488 6489 6490 6491 6492 6493 6494 6495 6496 6497 6498 6499 6500 6501 6502 6503 6504 6505 6506 6507 6508 6509 |
# File 'lib/parse/query.rb', line 6471 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).
6461 6462 6463 |
# File 'lib/parse/query.rb', line 6461 def sort(direction = :asc) order(direction) end |
#sum(field) ⇒ Hash
Sum a field for each time period.
6526 6527 6528 6529 6530 6531 6532 6533 |
# File 'lib/parse/query.rb', line 6526 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 |