Skip to content

Latest commit

 

History

History
93 lines (67 loc) · 3.04 KB

7.query.md

File metadata and controls

93 lines (67 loc) · 3.04 KB
title Query
description The Query base class and the ways to execute a query, with run(), await, a cursor, or for await...of, plus lazy composition.
mode reference

The Query<T> class is the base class of every AQL query type. It implements PromiseLike<T>, so you can await a query directly. It also provides cursor-based async iteration that yields results one at a time.

Class definition

class Query<T> extends StagedObject implements PromiseLike<T> {
  run(): Promise<T>;
  then<TResult1 = T, TResult2 = never>(
    onfulfilled?: ((value: T) => TResult1 | PromiseLike<TResult1>) | null,
    onrejected?: ((reason: any) => TResult2 | PromiseLike<TResult2>) | null,
  ): PromiseLike<TResult1 | TResult2>;
  cursor(): AsyncGenerator<T extends Array<infer U> ? U : T, void, unknown>;
  [Symbol.asyncIterator](): AsyncGenerator<
    T extends Array<infer U> ? U : T,
    void,
    unknown
  >;
}

Execute a query

run()

Executes the query pipeline and returns the result as a promise.

import { Schema } from "@antelopejs/interface-database";

const schema = Schema.get("myapp");
if (!schema) throw new Error("Define the myapp schema first");
const users = await schema.instance().table("users").run();

Direct await

Query implements PromiseLike, so you can await it directly without calling run():

const users = await schema.instance().table("users");

Both forms run the same stages: then() calls run().

Async iteration

A query whose result is an array yields one element at a time. A change feed yields one Changes<T> event per iteration. Atomic mutations are the exception. Their cursor() throws a TypeError, so await them directly or execute them with run().

cursor()

Returns an AsyncGenerator that yields results one at a time. Each next() call reads one result from the provider, so you can process a large result set without holding all of it at once.

const cursor = schema.instance().table("users").cursor();

let result = await cursor.next();
while (!result.done) {
  console.log("User:", result.value);
  result = await cursor.next();
}

for await...of

The [Symbol.asyncIterator]() method returns the query's cursor, which enables the for await...of syntax:

for await (const user of schema.instance().table("users")) {
  console.log("Processing:", user.name);
}

Query composition

Queries are lazy. Each operation records a pipeline stage, and the stages execute only when run(), then(), or iteration starts. You can therefore build queries step by step:

const usersTable = schema.instance().table("users");

// Build different queries from the same base
const activeUsers = usersTable.filter((u) => u.key("status").eq("active"));
const inactiveUsers = usersTable.filter((u) => u.key("status").eq("inactive"));

// Execute them independently
const active = await activeUsers;
const inactive = await inactiveUsers;