A PURE-ASH-QUERY reduce: the datastore does the grouping via a RELATIONSHIP
aggregate. The node's own resource is the group's resource — ONE row per group
— and over names its has_many to the rows being aggregated. The library loads
the aggregates in ONE Ash query — Postgres computes the GROUP BY — and each
parent row's aggregate values are its payload. No rows cross into the BEAM; no
into/read/upsert (contrast the in-BEAM reduce, which loads every row).
Only expressible as a relationship aggregate: the group must be a resource with
a relationship to the input. Arbitrary attribute GROUP BY is NOT in Ash 3.x's
read API — use the in-BEAM reduce (or a compute module) for that.
Each aggregate maps a kind (:count | :sum | :avg | :min | :max | :first) to a
{source_field, dest_attribute} (or, for :count, just a dest attribute):
aggregate over: :dmr_reports, # has_many on THIS resource
count: :day_count, # count(dmr_reports) → :day_count
avg: [flow: :avg_flow], # avg(dmr_reports.flow) → :avg_flow
max: [flow: :peak_flow]