Queries
A query is a document that reads facts and gives rows. It writes nothing. A
query needs find, and most queries add where.
Query execution measures CPU work on its thread, in 100-nanosecond ticks. Its budget includes planning, scans, expressions and result construction. Bounds describes the limits. The public API returns rows. Optional explain records give measurements for individual calls.
The examples with result blocks read these five entities. This merge patch creates them in a fresh database: Ada has ID 1, Bob 2, Cy 3, Dan 4 and Eve 5. The returned commit records these IDs for the patch's temporary names.
#_ada {name Ada
role engineer
age 36
dept eng
salary 120}
#_bob {name Bob
role engineer
age 41
mentor {#link #_ada}
dept eng
salary 100}
#_cy {name Cy
role designer
age 29
dept sales
salary 90}
#_dan {name Dan
dept sales
salary 70}
#_eve {name Eve
dept ops
salary 80}
Find and where
find gives the columns. where gives the clauses that bind them. A variable
that appears in more than one clause joins those clauses.
find [?name ?sal]
where [[?e dept ?dept]
[?e salary ?sal]
[?e name ?name]]
orderBy [?name]
[{name Ada
sal 120}
{name Bob
sal 100}
{name Cy
sal 90}
{name Dan
sal 70}
{name Eve
sal 80}]Clauses
A where clause has one of these forms.
| Kind | Shape | Purpose |
|---|---|---|
| Fact | [?e field ?v] | Matches stored facts |
| Member | [member ?e field ?key ?v] | Matches members of an object field |
| Negation | [not [...]] | Drops each solution that matches inside |
| Predicate | [> ?v 5] | Keeps each solution the expression accepts |
| Derivation | [[expression] ?out] | Binds a calculated value to a new variable |
| Schema | [schema name ?e] | Keeps entities that match a stored schema |
A fact clause has an entity, a field and a value. Each position accepts a
variable, a literal, or _ for a position that you do not read. An entity
position also accepts an entity reference such as {#link 1}, the id of
that entity. A fourth term binds the transaction of the fact.
A member clause reads each immediate member of an object field. It binds the member name as a string and the member value as stored. A sixth term can bind the transaction of the field.
find [?key ?artist]
where [[member ?track artists ?key ?artist]]
For example, this field has one member. Its name is a MusicBrainz GID. Its value
is a link to artist entity 8306.
artists {af1e76f062864cd4b4989a72a8df7de1 {#link 8306}}
If you do not need the member name, use _. A bound link value and a known field
use the reference index for current reads. The engine then checks the current
object to exclude removed or changed links.
find [?title]
where [[?artist
name
John Lennon]
[member ?track artists _ ?artist]
[?track track _]
[?track name ?title]]
Member clauses accept objects. Arrays and tagged scalar values have no matching
members. Two keys with the same value produce two matches. Use distinct true
to remove repeated result rows. An ordinary fact clause still reads the complete
field value.
A negation drops each solution that matches the clause inside it.
find [?name]
where [[?e name ?name]
[not [?e dept eng]]]
orderBy [?name]
[{name Cy} {name Dan} {name Eve}]A predicate keeps each solution that its expression accepts.
find [?name]
where [[?e salary ?sal]
[?e name ?name]
[> ?sal 85]]
orderBy [?name]
[{name Ada} {name Bob} {name Cy}]A derivation calculates a value and binds it to a new variable. The expression comes first, and the new variable follows it.
find [?name ?double]
where [[?e salary ?sal]
[?e name ?name]
[[* ?sal 2] ?double]]
orderBy [?name]
[{name Ada
double 240}
{name Bob
double 200}
{name Cy
double 180}
{name Dan
double 140}
{name Eve
double 160}]A schema clause keeps the entities whose current document matches a stored
schema. It names the schema by its path below definitions/schemas, without a
suffix. A stored schema supplies the validation rule.
Exact indexes
An exact index maps the values of a field to the entities that hold them. Stardust makes one for each field that a stored query or mutation compares with a value:
- a fact clause with a constant or parameter value, such as
[?e dept sales]or[?e dept ?dept]when?deptis a parameter. - a
=,<,<=,>or>=predicate on the value of a fact clause, such as[?e age ?age]with[>= ?age 18]. - an
inpredicate on the value of a fact clause, with a list of constants or a list parameter. For example,[?e name ?name]with[in ?name ?names]reads only the listed values.
The database maintains exact indexes for fields that stored definitions or ad-hoc native runs compare. A scan gives the same rows while an index is not yet active. The engine tracks index status internally.
Parameters
A ?variable that no clause binds becomes a required input when only a
predicate, a derivation or a having entry reads it. Stardust rejects an evaluation without a value for it.
find [?name]
where [[?e salary ?sal]
[?e name ?name]
[> ?sal ?floor]]
orderBy [?name]
Error
Missing_Parameter
The caller gives the value with the query. With floor set to 95:
- floor
- 95
[{name Ada} {name Bob}]A parameters block gives a default instead, which makes the input optional.
A declaration key uses ?name, like every other binding.
parameters {?floor 95}
find [?name]
where [[?e salary ?sal]
[?e name ?name]
[> ?sal ?floor]]
orderBy [?name]
[{name Ada} {name Bob}]A variable that no clause binds, and that no predicate reads, is an error. In
this query, no clause binds ?dept:
find [?name ?dept]
where [[?e name ?name]]
Error
Unbound_Variable
Result mode
A query gives one object for each row, keyed by the find columns. With
resultMode positional, it gives one list for each row, in find order.
find [?name ?sal]
where [[?e salary ?sal]
[?e name ?name]]
orderBy [?name]
resultMode positional
[[Ada 120] [Bob 100] [Cy 90] [Dan 70] [Eve 80]]
Project shapes each row into a document instead. Grouping adds aggregates and window functions.