Preview Release See the table of contents

Queries

The Query API lies at the heart of BeQue. If you’ve used SQL query builders like Knex before, you’ll feel right at home with BeQue’s Query API.

Construction, chaining, and execution

BeQue queries are always for a specific type of object, like a Transaction or an NFT. You can create a new query by calling that object’s query() method:

import { Transaction } from "@beque/base-eth";

// Construct a query for literally all Ethereum transactions, ever.
const query = Transaction.query();
// At this point, the query has not been executed.

Queries are chainable. For instance, to construct a query for the past day’s Transactions:

const query = Transaction.query().where("date", ">=", ONE_DAY_AGO);

To execute a query, coerce it into a promise state by calling its then(...) method or await-ing it:

const results = await Transaction.query().where("date", ">=", ONE_DAY_AGO);

The exact type of results is dependent on the query issued. For instance, the query above will return a Transaction[]; a query that appended .first() would return Transaction | null. The BeQue SDK works hard to keep static types sensible even for complex queries.

Pagination

The BeQue cloud service limits individual HTTP responses to a large but sensible size. In order to support massive queries, BeQue offers pagination support.

To paginate a query, construct a query that uses an orderBy(...) clause and send it to a Paginator instance. Queries without such an explicit order will have inconsistent pagination behavior.

import { Paginator } from "@beque/utils";

// to ensure stable pagination, all paginated queries should have order-by clauses
const query = Transaction.query()
  .where("date", ">=", ONE_DAY_AGO)
  .orderBy("id");
const paginator = new Paginator(query, { pageSize: 50 });
const pageCount = await paginator.pageCount();
for (let i = 0; i < pageCount; i++) {
  const pageResults = await paginator.getPage(i);
  // do fun stuff here...
}

QueryBuilder: where methods

BeQue’s where(...) methods allow for the construction of complex filtering queries.

Like all methods in BeQue’s QueryBuilder type, where(...) methods can be chained to one another. By default, two chained where(...) methods result in a logical AND clause; every variant of where(...) also has an orWhere(...) variant to allow for constructing logical OR clauses.

» where(col: string, rhs: unknown)

Filter results to those whose column col has the value rhs.

For instance, Transaction.query().where("amount", 1_000_000) returns transactions whose amount is precisely 1 million.

» where(cols: Record<string, unknown>)

Filter results based on equality, potentially across multiple columns.

For instance, Transaction.query().where({amount: 1_000_000, date: TODAY}) returns today’s transactions whose amount is 1 million.

» where(col: string, op: Op, rhs: unknown)

Filter results based on a comparison.

For instance, Transaction.query().where("amount", ">=", 1_000_000) returns transactions whose amount is 1 million or more.

» where(fn: (builder: QueryBuilder) => QueryBuilder)

Create a query subgroup.

For instance, the following code creates a query that looks for NFTs purchased for over $50 in the past week, or over $25 in the past two:

import { Trade } from "@beque/nft";

const query = Trade.query()
  .where((q) =>
    q.where("date", ">=", ONE_WEEK_AGO).where("usdAmount", ">=", 50)
  )
  .orWhere((q) =>
    builder.where("date", ">=", TWO_WEEKS_AGO).where("usdAmount", ">=", 25)
  );

QueryBuilder: methods

» limit(count: number)

Limit results to a maximum count. The exact number of results returned by differ.

» offset(index: number)

Return results starting at index. The query should have an ordering; if it does not, repeated invocations may return different results.

» orderBy(col: string)

Order results by the values in a specific column. Order is ascending by default; prefix the column name with "-" to obtain descending order.

» first()

Return the first result only. If there are no results, returns null.

More documentation forthcoming

Stay tuned for documentation about joins, grouping, etc.