Skip to main content

Views

Views are saved, named configurations of how a table's records are filtered, sorted, grouped, and projected. Add them under a table's views array. A view operates in one of two modes: JSON config mode (declarative filters/sorts/fields/group-by) or SQL mode (a raw PostgreSQL query).

View Properties

Property Description
id Unique view identifier.
name Human-readable view name.
isDefault Boolean. When true, this view's configuration applies when no specific view is requested.
filters Filter conditions (JSON config mode). See below.
sorts Array of { field, direction } sort rules (JSON config mode). direction is asc or desc.
fields Array of field names to include, in display order (JSON config mode).
groupBy { field, direction? } grouping configuration (JSON config mode).
query Raw SQL for a PostgreSQL VIEW (SQL mode). When set, JSON config properties are not used.
materialized Boolean. With query, create a MATERIALIZED VIEW that caches results. SQL mode only.
refreshOnMigration Boolean. With materialized, refresh the materialized view during migrations.

JSON Config Mode

Declarative — filter, sort, group, and choose columns without writing SQL.

views:
  - id: active_high_priority
    name: Active — High Priority
    isDefault: true
    filters:
      and:
        - { field: status, operator: equals, value: active }
        - { field: priority, operator: equals, value: high }
    sorts:
      - { field: created_at, direction: desc }
    fields: [title, status, priority, assigned_to]
    groupBy: { field: status, direction: asc }

Filters

A filter is either a single condition { field, operator, value } or a boolean group combining conditions with and / or (which may nest):

filters:
  or:
    - { field: priority, operator: equals, value: high }
    - { field: priority, operator: equals, value: urgent }

Common operators include equals, greaterThan, lessThan, and similar comparison operators. See Validation for how filter fields are checked against the table.

SQL Mode

For advanced reporting, provide a raw query. Set materialized: true to cache the results, and refreshOnMigration: true to keep the cache fresh across schema migrations.

views:
  - id: monthly_revenue
    name: Monthly Revenue
    query: >
      SELECT date_trunc('month', created_at) AS month, SUM(amount) AS revenue
      FROM orders GROUP BY 1 ORDER BY 1
    materialized: true
    refreshOnMigration: true