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.
7094 7095 7096 7097 7098 7099 7100 7101 7102 7103 |
# File 'lib/parse/query.rb', line 7094 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.
7226 7227 7228 7229 7230 7231 7232 7233 |
# File 'lib/parse/query.rb', line 7226 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.
7204 7205 7206 |
# File 'lib/parse/query.rb', line 7204 def count execute_date_aggregation("count", { "$sum" => 1 }) end |
#max(field) ⇒ Hash
Find maximum value of a field for each time period.
7252 7253 7254 7255 7256 7257 7258 7259 |
# File 'lib/parse/query.rb', line 7252 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.
7240 7241 7242 7243 7244 7245 7246 7247 |
# File 'lib/parse/query.rb', line 7240 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.
7119 7120 7121 7122 7123 7124 7125 7126 7127 7128 7129 7130 7131 7132 7133 7134 7135 7136 7137 7138 7139 7140 7141 7142 7143 7144 |
# File 'lib/parse/query.rb', line 7119 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.
7159 7160 7161 7162 7163 7164 7165 7166 7167 7168 7169 7170 7171 7172 7173 7174 7175 7176 7177 7178 7179 7180 7181 7182 7183 7184 7185 7186 7187 7188 7189 7190 7191 7192 7193 7194 7195 7196 7197 |
# File 'lib/parse/query.rb', line 7159 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).
7149 7150 7151 |
# File 'lib/parse/query.rb', line 7149 def sort(direction = :asc) order(direction) end |
#sum(field) ⇒ Hash
Sum a field for each time period.
7214 7215 7216 7217 7218 7219 7220 7221 |
# File 'lib/parse/query.rb', line 7214 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 |