Query Syntax#
Overview#
Generally queries will consist of a where clause plus optional modifiers controlling the specific subset of results returned.
Where Clause#
The Where clause is an optional array of conditions. If omitted or empty, all documents of the queried type are returned (subject to limit). For some operators, value will be an array. All fields referenced in a query’s where clause must be defined in the same index. This includes system timestamp fields (e.g., $createdAt, $updatedAt, $transferredAt, and their block-height variants such as $createdAtBlockHeight and $createdAtCoreBlockHeight). See the following general syntax example:
{
where: [
[<fieldName>, <operator>, <value>],
[<fieldName>, <array operator>, [<value1>, <value2>]]
]
}
Fields#
Valid fields consist of the indices defined for the document being queried. For example, the DPNS data contract defines two indices for domain documents:
Index Field(s) |
Index Type |
Unique |
|---|---|---|
Compound |
Yes |
|
Single Field |
No |
Comparison Operators#
Equal#
Name |
Description |
|---|---|
== (or =) |
Matches values that are equal to a specified value |
Range#
Name |
Description |
|---|---|
< |
Matches values that are less than a specified value |
<= |
Matches values that are less than or equal to a specified value |
>= |
Matches values that are greater than or equal to a specified value |
> |
Matches values that are greater than a specified value |
in |
Matches all document(s) where the value of the field equals any value in the specified array |
Between |
Matches values between two bounds (inclusive on both sides) — value must be a two-element array |
BetweenExcludeBounds |
Matches values strictly between two bounds (exclusive on both sides) |
BetweenExcludeLeft |
Matches values between two bounds, excluding the lower bound |
BetweenExcludeRight |
Matches values between two bounds, excluding the upper bound |
Tip
Only one range operator is allowed in a query.
Betweenand its variants are single operators that replace a>=/<=pair — the engine also normalizes two range operators on the same field into the equivalentBetween*form automaticallyThe
inoperator is only allowed for last two indexed propertiesRange operators are only allowed after
==andinoperatorsRange operators are only allowed for the last two fields used in the where condition
Queries using range operators must also include an
orderBystatement
Evaluation Operators#
Name |
Description |
|---|---|
startsWith |
Selects documents where the value of a field begins with the specified characters. Must include an |
Operator Examples#
{
where: [
["nameHash", "<", "56116861626961756e6176657a382e64617368"],
],
}
{
where: [
["normalizedParentDomainName", "==", "dash"],
// Return names between "alice" and "carol" (inclusive)
["normalizedLabel", "Between", ["alice", "carol"]],
],
orderBy: [
["normalizedLabel", "asc"],
]
}
{
where: [
["normalizedParentDomainName", "==", "dash"],
// Return all matching names from the provided array
["normalizedLabel", "in", ["alice", "bob"]],
]
}
{
where: [
["normalizedParentDomainName", "==", "dash"],
// Return any names beginning with "al" (e.g. alice, alfred)
["normalizedLabel", "startsWith", "al"],
],
orderBy: [
["normalizedLabel", "asc"],
]
}
Query Modifiers#
The query modifiers described here determine how query results will be sorted and what subset of data matching the query will be returned.
Modifier |
Effect |
Example |
|---|---|---|
|
Restricts the number of results returned (maximum: 100) |
|
|
Returns records sorted by the field(s) provided. Sorting must be by the last indexed property. Can only be used with |
|
|
Returns records beginning with the document ID provided |
|
|
Returns records beginning after the document ID provided |
|
|
Skips the first N matching results (available at the CBOR/DAPI layer; not exposed in the JS SDK) |
|
Attention
For indices composed of multiple fields (example from the DPNS data contract), the sort order in an orderBy must either match the order defined in the data contract OR be the inverse order.
Aggregate Queries#
Added in version 3.1.0.
The getDocuments v1 surface adds an aggregate-query mode. The same where / orderBy clauses described above still apply; an additional select projection (and optional groupBy) determines whether the request returns documents or aggregate values over the matched set.
|
Returns |
|---|---|
|
Matched documents (same as v0). |
|
Number of documents matching the query. |
|
Sum of |
|
|
groupBy is optional. With an empty groupBy, the response carries a single aggregate value; with a groupBy of one or two fields, the response carries one entry per group.
Aggregate queries impose extra schema requirements on the document type — COUNT needs documentsCountable, SUM needs documentsSummable, AVG needs documentsAverageable (or both base flags). Range-grouped aggregates additionally need the range* variants. See the doctype-level aggregate flags for the schema annotations and the getDocuments reference for the full select × groupBy shape table.
SUM / AVG integer values are returned as JS strings so JavaScript clients don’t lose precision on values larger than Number.MAX_SAFE_INTEGER.
Note
HAVING, OFFSET, COUNT(<field>), MIN, MAX, and multi-projection SELECT are present on the wire but currently return Unsupported. Callers can encode them in builders ahead of server support landing, but evaluation rejects them today.
Example query#
The following query combines both a where clause and query modifiers.
const query = {
limit: 5,
startAt: '4Qp3menV9QjE92hc3BzkUCusAmHLxh1AU6gsVsPF4L2q',
where: [
['normalizedParentDomainName', '==', 'dash'],
['normalizedLabel', 'startsWith', 'test'],
],
orderBy: [
['normalizedLabel', 'asc'],
],
}
import { EvoSDK } from '@dashevo/evo-sdk';
const sdk = EvoSDK.testnetTrusted();
await sdk.connect();
const results = await sdk.documents.query({
dataContractId: 'GWRSAVFMjXx8HpQFaNJMqBV7MBgMK4br5UESsB4S31Ec',
documentTypeName: 'domain',
limit: 5,
startAt: '4etYFuWbXRXB74gTDp53eLUqjLEAtNSfUX2XtrQ1uMdT',
where: [
['normalizedParentDomainName', '==', 'dash'],
['normalizedLabel', 'startsWith', 'test'],
],
orderBy: [
['normalizedLabel', 'asc'],
],
});
for (const [id, doc] of results) {
console.log(id.toString(), doc?.toJSON());
}