Skip to main content

ParadeDB Operator

In order for ParadeDB to push down an aggregate, a ParadeDB text search operator must be present in the query.
-- Not pushed down
SELECT COUNT(id) FROM mock_items
WHERE rating = 5;

-- Pushed down
SELECT COUNT(id) FROM mock_items
WHERE rating = 5
AND id @@@ pdb.all();
If your query does not contain a ParadeDB operator, a way to “force” aggregate pushdown is to append the all query to the query’s WHERE clause.

Join Support

Aggregate pushdown works across joins as well as single tables. When every participating table has a BM25 index and the custom aggregate scan is enabled, ParadeDB computes the result directly from the index’s columnar storage, without scanning the underlying table rows.
SET paradedb.enable_aggregate_custom_scan TO on;
The following join shapes are supported:
FeatureSupported
Join typesINNER, LEFT, RIGHT, FULL OUTER
Number of tablesTwo or more (arbitrary join trees)
Aggregate functionsCOUNT, COUNT(DISTINCT ...), SUM, SUM(DISTINCT ...), AVG, AVG(DISTINCT ...), MIN, MAX, STDDEV, STDDEV_POP, VARIANCE, VAR_POP, BOOL_AND, BOOL_OR, ARRAY_AGG, STRING_AGG
GROUP BYColumns from any table in the join, including JSON sub-fields via metadata->>'key'
HAVING clauseComparisons against aggregate results and group columns
Per-aggregate FILTER (WHERE ...)Yes
ORDER BY ... LIMIT KPushed down as TopK when there is a single ORDER BY column targeting an aggregate, a group column, or MIN(col) / MAX(col)
ORDER BY inside STRING_AGG / ARRAY_AGGYes (produces deterministic element ordering)
ParadeDB falls back to native Postgres execution when any of the following are true:
  • One or more tables in the join lacks a BM25 index
  • The join has no equality join condition (e.g. CROSS JOIN)
  • Join keys, GROUP BY columns, or aggregate arguments are not indexed columns
  • The query uses window functions (OVER ...), ROLLUP, CUBE, GROUPING SETS, LATERAL, or DISTINCT ON
  • GROUP BY uses a scalar function like date_trunc(...) or lower(...) (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
  • The query uses pdb.agg() (use standard SQL aggregate functions instead)
When a fallback happens, the query still runs correctly through Postgres’ native planner. ParadeDB simply does not accelerate it.
Aggregate pushdown across joins is currently single-threaded. Parallel execution is on the roadmap.

NUMERIC Columns

NUMERIC columns do not support aggregate pushdown. Queries with aggregates on NUMERIC columns will automatically fall back to PostgreSQL for aggregation. For numeric data that requires aggregate pushdown, use FLOAT or DOUBLE PRECISION instead:
-- Aggregates can be pushed down
CREATE TABLE products (
    id SERIAL PRIMARY KEY,
    price DOUBLE PRECISION
);

-- Aggregates fall back to PostgreSQL
CREATE TABLE products (
    id SERIAL PRIMARY KEY,
    price NUMERIC(10,2)
);
Filter pushdown (equality and range queries) is fully supported for all NUMERIC columns. Only aggregate pushdown is not supported.