Skip to content

Queries and computed values

Queries describe the read side of the product. They are not generated automatically from every object because a list of database rows is rarely the actual question an actor needs answered.

Good queries express a product question:

  • GetMyUpcomingAppointments
  • ListUnassignedCases
  • DailyRevenueByClinic
  • GetOrderWithFulfillmentStatus

A query declares its target, parameters, output fields, filters, sort order, return cardinality, pagination behavior, authorized actors, and row scope.

Keep three concepts separate:

  • Parameters are values the caller supplies, such as a date range.
  • Filters are predicates the query always applies, such as status = pending or assignedAt is set.
  • Scopes restrict rows based on the current actor.

A “pending” worklist should contain a declared filter; the generator should not infer it from the query’s English name. Scope must be applied before filtering results for pagination totals.

Each output field can come from:

  • a stored attribute on an object;
  • a structured computed expression;
  • an external source with a declared integration contract.

Explicit source mappings let backend projections, frontend columns, exports, and tests agree.

Use computed values for deterministic read-time derivations such as totals, counts, duration, conditional labels, or ratios. Prefer a structured expression over prose the generator must parse.

Ask whether the value should be:

  • computed from current rows on every read;
  • stored and updated by commands;
  • pre-aggregated for performance;
  • obtained from another system.

That choice affects consistency and scalability. A formula that is correct for ten rows may need a materialized strategy at ten million; the model or infrastructure intent must expose the workload constraint instead of hiding it in hand-edited code.

Declare a stable default sort. Pagination without deterministic ordering can repeat or skip rows as data changes. Choose a page size appropriate to the experience and provide bounded limits.

Reports are modeled queries with semantic outputs, not screenshot instructions. Design can project the same query into a table, metric, chart, timeline, or export.

For each report, identify:

  • the actor and decision it supports;
  • the time grain and timezone;
  • filters and dimensions;
  • aggregation semantics;
  • acceptable freshness;
  • expected data volume.

Generation should block when a field source, aggregate, filter field, parameter, scope predicate, or sort field cannot resolve. A query that compiles but silently omits a requested calculation is not a successful projection.

See Views and patterns for presentation and Infrastructure for read-side caching options.