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.
7259 7260 7261 7262 7263 7264 7265 7266 7267 7268 |
# File 'lib/parse/query.rb', line 7259 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.
7390 7391 7392 7393 7394 7395 7396 7397 |
# File 'lib/parse/query.rb', line 7390 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.
7368 7369 7370 |
# File 'lib/parse/query.rb', line 7368 def count execute_date_aggregation("count", { "$sum" => 1 }) end |
#max(field) ⇒ Hash
Find maximum value of a field for each time period.
7416 7417 7418 7419 7420 7421 7422 7423 |
# File 'lib/parse/query.rb', line 7416 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.
7404 7405 7406 7407 7408 7409 7410 7411 |
# File 'lib/parse/query.rb', line 7404 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.
7284 7285 7286 7287 7288 7289 7290 7291 7292 7293 7294 7295 7296 7297 7298 7299 7300 7301 7302 7303 7304 7305 7306 7307 7308 |
# File 'lib/parse/query.rb', line 7284 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.
7323 7324 7325 7326 7327 7328 7329 7330 7331 7332 7333 7334 7335 7336 7337 7338 7339 7340 7341 7342 7343 7344 7345 7346 7347 7348 7349 7350 7351 7352 7353 7354 7355 7356 7357 7358 7359 7360 7361 |
# File 'lib/parse/query.rb', line 7323 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).
7313 7314 7315 |
# File 'lib/parse/query.rb', line 7313 def sort(direction = :asc) order(direction) end |
#sum(field) ⇒ Hash
Sum a field for each time period.
7378 7379 7380 7381 7382 7383 7384 7385 |
# File 'lib/parse/query.rb', line 7378 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 |