6.1 The query service: stored queries authored like files
A store can list and page, but it can't filter by field (4.4). The query
service fills that gap: you author stored, parameterized queries and execute
them over your data. Queries are authored like files — no tenant-config round
trip — and run on any HTTP verb.
Mounting it
{ "path": "/q", "service": "query",
"config": { "access": { "write": "A" } } }
Two surfaces: authoring and execution
A query mount has two faces, which is the store-view pattern (3.4):
- Authoring — a reserved subtree,
/<mount>/.queries/…, that obeys the full store contract (PUT/GET/DELETE, listings, ETags). This is where query specs live. Guard authoring withwrite(e.g.write: "A"). - Execution — every other path under the mount, on any verb, runs the longest-prefix-matched stored query.
So you PUT a query spec to .queries/open-orders, then run it with
GET /q/open-orders?status=open. Authoring and running are different paths, so a
query can serve a plain GET to ordinary clients while only admins can edit it.
A query spec (the envelope)
{ "language": "json",
"query": { "dataset": "orders",
"where": { "status": "${status}",
"total": { "op": ">=", "value": "${min}" } },
"orderBy": "total" },
"params": { "type": "object", "required": ["status"],
"properties": { "status": { "type": "string" },
"min": { "type": "number", "default": 0 } } },
"output": { "type": "array" } }
query— the query itself, in the backing language (here the reference adapter's JSON form).params— a JSON Schema for the inputs: types,required, anddefaults.output— describes the result shape (surfaced on the agent surface).language— optional; inferred (jsonfor a JSON template,sqlfor a string template).
The envelope is validated at PUT time — a bad envelope or a non-compiling
param schema is a 400 at write, not a surprise at execution.
The reference adapter
Out of the box, a JSON query runs against a data dataset via the reference
adapter: where clauses AND together, field names may be dot-paths, ops are
== (default) != < > <= >= contains, orderBy sorts, and each row
gains a _key. Results come back as a JSON array with X-Total-Count, pageable
with $take/$skip.
The backing language is pluggable (QueryStore capability): the same envelope
shape can drive Mongo aggregates, an Elastic DSL, or a SQL adapter (6.4).
The next sections cover how parameters get in, and how the two template kinds (JSON vs. string/SQL) substitute them safely.
← Part 5 — Auth & Access Control · Manual home · Next: 6.2 Parameters →