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.
6813 6814 6815 6816 6817 6818 6819 6820 6821 6822 |
# File 'lib/parse/query.rb', line 6813 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.
6945 6946 6947 6948 6949 6950 6951 6952 |
# File 'lib/parse/query.rb', line 6945 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.
6923 6924 6925 |
# File 'lib/parse/query.rb', line 6923 def count execute_date_aggregation("count", { "$sum" => 1 }) end |
#max(field) ⇒ Hash
Find maximum value of a field for each time period.
6971 6972 6973 6974 6975 6976 6977 6978 |
# File 'lib/parse/query.rb', line 6971 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.
6959 6960 6961 6962 6963 6964 6965 6966 |
# File 'lib/parse/query.rb', line 6959 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.
6838 6839 6840 6841 6842 6843 6844 6845 6846 6847 6848 6849 6850 6851 6852 6853 6854 6855 6856 6857 6858 6859 6860 6861 6862 6863 |
# File 'lib/parse/query.rb', line 6838 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.
6878 6879 6880 6881 6882 6883 6884 6885 6886 6887 6888 6889 6890 6891 6892 6893 6894 6895 6896 6897 6898 6899 6900 6901 6902 6903 6904 6905 6906 6907 6908 6909 6910 6911 6912 6913 6914 6915 6916 |
# File 'lib/parse/query.rb', line 6878 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).
6868 6869 6870 |
# File 'lib/parse/query.rb', line 6868 def sort(direction = :asc) order(direction) end |
#sum(field) ⇒ Hash
Sum a field for each time period.
6933 6934 6935 6936 6937 6938 6939 6940 |
# File 'lib/parse/query.rb', line 6933 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 |