Skip to content

Analytics

The analytics contract runs registered, parametrized queries against a warehouse table or view and returns typed rows, with an optional append-only ingest side. Unlike the document port it has no per-row CRUD and no live query DSL — you register named queries up front and pass typed params; unlike procedures it only reads. The concept is Analytics; the worked flow is the analytics-over-a-data-lake recipe.

rows = await ctx.analytics.query(spec).run("by_region", params)   # registered query → typed rows
await ctx.analytics.ingest(spec).append(new_rows)                 # append-only bulk load

Spec

AnalyticsSpec[R, Ing] — the read-row model, the named queries, and an optional ingest model:

Field Type Default Meaning
name str \| StrEnum required logical name / warehouse route
read type[R] required default read model for result rows
queries Mapping[str, AnalyticsQueryDefinition] required named queries (≥1); each declares a typed params model
ingest type[Ing] \| None None append-row model; None disables ingest
encryption FieldEncryption \| None None seal columns at rest (confidential, not aggregatable; binds_record_id unsupported — rows have no id)
read_codec / ingest_codec ModelCodec \| None None codec overrides (auto-derived otherwise)

Each AnalyticsQueryDefinition carries a Pydantic params model — the typed arguments a run* call passes — and an optional description.

Query port (ctx.analytics.query(spec))

Run a registered query by key with typed params; the shape × pagination naming mirrors the document query port:

Method Result
run(query_key, params, pagination=None, *, options=None) CountlessPage[R]
run_page(...) Page[R] (with .count when the backend supports it)
run_cursor(...) CursorPage[R] (keyset)
run_chunked(..., fetch_batch_size=2000) async generator of row batches
project_run* / select_run* JsonDict / caller-typed-model variants

options: AnalyticsRunOptions carries the per-run knobs — dry_run, max_rows, and timeout.

Ingest port (ctx.analytics.ingest(spec))

Method Signature Notes
append append(rows) append-only bulk insert; returns an AnalyticsAppendResult (accepted / rejected / errors), or None when the backend reports nothing

Ingest is append-only — no update or delete. To recompute a rollup over an ingested batch, reach for the procedures port rather than per-row writes.

Implemented by

Backend Notes Integration
Postgres tables / views Postgres
ClickHouse columnar warehouse ClickHouse
BigQuery serverless warehouse BigQuery
DuckDB in-process / data-lake (query-only; tenancy ceiling tagged) DuckDB