17. Executable Entity Queries
Blueprint query execution uses the same Vyuh Query objects for views, filters, sorting, grouping, paging, HTTP transport, subscriptions, and caches.
Choose a projection, refine the query, then read once or watch for changes.
Bind one entity projection
import 'package:vyuh_query/vyuh_query.dart' as query;
final equipmentQuery = query.EntityQuery<Map<String, Object?>>(
entity: const query.EntitySource(
entityType: 'manufacturing.equipment',
projectionRef: 'summary',
),
fetch: const query.OffsetFetchRequest(offset: 0, limit: 20),
executor: executor,
);EntityQuery<T> is immutable. T is the decoded record type: generic clients may use a map or projection object, while a generated client may use a domain class.
Refine without losing the base filter
final ready = equipmentQuery
.where(
const query.QueryTerm(
field: query.QueryFieldRef('cleaning.status'),
op: query.QueryOp.equals,
arg: query.ArgValue('ready'),
).expr,
)
.orderBy([
const query.Sort(
field: query.QueryFieldRef('identity.code'),
direction: query.SortDirection.asc,
),
]);
final page = await ready.get();where takes a vyuh_expression Expr<bool>; QueryTerm(...).expr writes one field test, and And, Or and Not combine them. It combines client filters with the existing query. It never replaces a server-owned baseFilter. The server validates the entity, projection, field, operator, and operand before compiling the query.
Execute once or subscribe
final current = await ready.get();
final subscription = ready.subscribe().listen((next) {
if (next case query.FlatFetchResponse(:final records)) {
render(records);
}
});An EntityQueryExecutor<T> can be backed by the Blueprint server, HTTP, in-process execution, a query cache, a test double, or a generated SDK. A subscription emits complete query values. Server invalidations carry no rows; the executor reruns the authoritative request so policy, projection rules, base filters, paging, and current database state are applied together.
Derive a query from a declared view
final viewQuery = query.EntityQuery<Map<String, Object?>>.fromView(
equipmentView,
executor: executor,
layoutId: 'table',
);The selected layout contributes its arrangement and fetch window. Dataset and relationship views are rejected because EntityQuery always has one concrete entity anchor.
Understand current advanced-field behavior
Time, binary, geospatial, range, network, vector, and typed-object fields have portable codecs and storage lowering. The query layer currently maps supported fields onto its existing scalar and collection operator families. Binary fields are omitted from generic query UI. Blueprint does not expose spatial distance, nearest-neighbor, range-containment, or vector-similarity operators as dedicated query vocabulary.
Checkpoint
Build a query that:
- targets
manufacturing.equipment.summary; - filters
cleaning.status == ready; - retains a server-owned tenant base filter;
- orders by
identity.code; - executes through both
get()andsubscribe().
References: UI, Queries, and Forms