ParadeDB Predicate
In order for ParadeDB to push down an aggregate, a ParadeDB predicate must be present in the query.WHERE clause.
Date Grouping
GROUP BY DATE(created_at) and GROUP BY created_at::date support aggregate pushdown when created_at is a bare timestamp without time zone column that is columnar indexed. The usual aggregate pushdown requirements still apply, including a ParadeDB operator in the query.
The result matches Postgres for the full timestamp range, including infinity, -infinity and NULL. Date grouping can be combined with other grouping columns and per-aggregate FILTER clauses.
The following forms still fall back to native Postgres execution:
DATE(timestamptz_column), because the result depends on the sessionTimeZone.DATE(text_column::timestamp)and other non-bare timestamp expressions.- Other scalar grouping functions, such as
date_trunc(...)andlower(...).
Join Support
Aggregate pushdown works across joins as well as single tables. When every participating table has a ParadeDB index, ParadeDB computes the result directly from the index’s columnar storage, without scanning the underlying table rows. The custom aggregate scan is enabled by default; to turn it off, runSET paradedb.enable_aggregate_custom_scan TO off;.
Supported shapes
pdb.agg() over joins
A pdb.agg() field name must belong to exactly one indexed table in the join. When the same field name exists in several tables, qualify it with the table alias, as in "field": "p.category". The qualifier is also accepted when the planner reduces the join to that one table. Postgres cannot see the fields inside a spec, so an outer join whose table is read only there is removed as unused and the spec fails with an unknown field; reference such a table outside the spec, or use an inner join.
pdb.agg() over a NUMERIC field runs on this path as well, on a single table or over a join, while a missing value is not accepted for such a field. terms on an array field is also supported over joins; metric aggregations over array fields are not.
A few pdb.agg() shapes run on a single table but not over a join: metric aggregations over JSON sub-fields, such as {"sum": {"field": "metadata.qty"}}, terms on a JSON sub-field that holds numbers, and min_doc_count: 0, which lists every term of the column.
pdb.agg() has no native Postgres implementation, so it cannot fall back. A pdb.agg() over a join that uses an aggregation outside the list above, such as range, histogram, date_histogram, filter, composite, stats, percentiles, or top_hits, raises an error.
Fallback to Postgres
For aggregates over joins, ParadeDB falls back to native Postgres execution when any of the following are true:- One or more tables in the join lacks a ParadeDB index
- The join has no equality join condition (e.g.
CROSS JOIN) - Join keys,
GROUP BYcolumns, or aggregate arguments are not indexed columns - The query uses window functions (
OVER ...),ROLLUP,CUBE,GROUPING SETS,LATERAL, orDISTINCT ON. The single-table faceted query formpdb.agg(...) OVER ()is pushed down, but not across joins GROUP BYuses a scalar function likedate_trunc(...)orlower(...)(JSON sub-field access via->>is supported)- The aggregate argument or result is wrapped in an expression such as
COALESCE(SUM(...), 0)or a cast