Skip to main content

Operators

Verse provides many query operators to help you write sophisticated queries. This section will describe the built-in operators and how to use them.

all​

The all operator is used to check if all of the elements in a sequence satisfy a given condition:

const all = await db.from.artists.all(a => a.name !== "AC/DC"); // false

any​

The any operator is used to check if a sequence contains any elements:

let any = await db.from.artists.where(a => a.name === "AC/DC").any(); // true

There is a shorthand for the common case above:

any = await db.from.artists.any(a => a.name === "AC/DC"); // true

array​

The array operator is an aggregate operator that collects all the elements in a sequence into an array:

const array = await db.from.artists.array().first(); // true

Aggregation happens on the database side, usually using a JSON array aggregation function such as json_agg in PostgreSQL.

avg​

The avg operator is an aggregate operator that calculates the average of a sequence of numbers:

let avg = await db.from.artists.select(a => a.artistId).avg();

There is a shorthand for the common case above:

avg = await db.from.artists.avg(a => a.artistId);

count​

The count operator is an aggregate operator that counts the number of elements in a sequence:

const count = await db.from.artists.count();

distinct​

The distinct operator is used to remove duplicate elements from a sequence:

const distinct = await db.from.artists
.select(a => a.name)
.distinct()
.toArray();

first​

The first operator is used to get the first element of a sequence:

let first = await db.from.artists.where(a => a.name === "AC/DC").first();

There is a shorthand for the common case above:

first = await db.from.artists.first(a => a.name === "AC/DC");

groupBy​

The groupBy operator is used to group elements in a sequence by a key:

const groupBy = await db.from.albums.groupBy(a => a.artistId).toArray();

Each group is represented as a key-value pair where the key is the group key and the value is an array of the elements in the group.

You can also perform aggregation on the groups:

const albumCounts = await db.from.albums
.groupBy(
a => a.artistId,
g => ({
artist: g.key,
count: g.count(),
})
)
.toArray();

join​

The join operator is used to join two sequences based on a common key:

const joined = await db.from.artists
.join(db.from.albums, (ar, al) => ar.artistId === al.artistId)
.select((ar, al) => ({
artist: ar.name,
album: al.title,
}))
.toArray();

join returns a sequence of pairs where the first element is from the first sequence and the second element is from the second sequence. Subsequent operators (like the select operator above) will automatically destructure the pairs into separate parameters when the operator accepts an arrow function.

leftJoin​

The leftJoin operator is used to join two sequences based on a common key, returning all elements from the first sequence, and the matching elements from the second sequence:

const leftJoined = await db.from.artists
.leftJoin(db.from.albums, (ar, al) => ar.artistId === al.artistId)
.toArray();

Join returns a sequence of pairs where the first element is from the first sequence and the second element is from the second sequence, or undefined if there is no match. As with join, subsequent operators will automatically destructure the pairs into separate parameters when the operator accepts an arrow function.

limit​

The limit operator is used to limit the number of elements in a sequence:

const limit = await db.from.artists.limit(5).toArray();

Limit queries are automatically parameterized to improve performance and security.

max​

The max operator is an aggregate operator that calculates the maximum of a sequence of numbers:

let max = await db.from.artists.select(a => a.artistId).max();

There is a shorthand for the common case above:

avg = await db.from.artists.max(a => a.artistId);

maybeFirst​

The maybeFirst operator is used to get the first element of a sequence, or return undefined if the sequence is empty:

let maybeFirst = await db.from.artists
.where(a => a.name === "Allan Holdsworth")
.maybeFirst();

There is a shorthand for the common case above:

maybeFirst = await db.from.artists.maybeFirst(
a => a.name === "Allan Holdsworth"
);

maybeSingle​

The maybeSingle operator is used to get the only element of a sequence, or return undefined if the sequence is empty:

let maybeSingle = await db.from.artists
.where(a => a.name === "Allan Holdsworth")
.maybeSingle();

This operator will throw an error if the sequence contains more than one element.

There is a shorthand for the common case above:

maybeSingle = await db.from.artists.maybeSingle(
a => a.name === "Allan Holdsworth"
);

min​

The min operator is an aggregate operator that calculates the minimum of a sequence of numbers:

let min = await db.from.artists.select(a => a.artistId).min();

There is a shorthand for the common case above:

avg = await db.from.artists.min(a => a.artistId);

offset​

The offset operator is used to skip a number of elements in a sequence:

const offset = await db.from.artists.offset(5).toArray();

Offset queries are automatically parameterized to improve performance and security.

options​

The options operator is used to specify query options:

const options = await db.from.artists
.options({ disabledConditions: "all" })
.where(a => a.name === "AC/DC")
.toArray();

It may only be used at the beginning of a query.

orderBy​

The orderBy operator is used to sort elements in a sequence:

const ordered = await db.from.artists.orderBy(a => a.name).toArray();

orderByDesc​

The orderByDesc operator is used to sort elements in a sequence in descending order:

const orderedDesc = await db.from.artists.orderByDesc(a => a.name).toArray();

select​

The select operator is used to project elements in a sequence:

const select = await db.from.artists.select(a => a.name).toArray();

Complex projections are supported:

const selectComplex = await db.from.albums
.select(a => ({
id: a.albumId,
desc: `Title: ${a.title}`,
props: [a.artistId],
}))
.toArray();

Verse will push down projection expressions to the database when possible (such as the template literal above). The example above will be translated to SQL as:

select "t1"."AlbumId", 'Title: ' || "t1"."Title" as "c0", "t1"."ArtistId"
from "Album" as "t1"

The rest of the required projection processing (i.e creating each result object) will be performed on the client side.

single​

The single operator is used to get the only element of a sequence:

let single = await db.from.artists.where(a => a.name === "AC/DC").single();

Single will throw if there are no elements in the sequence, or if there is more than one element.

There is a shorthand for the common case above:

single = await db.from.artists.single(a => a.name === "AC/DC");

sql​

The sql operator is used to execute a raw SQL query:

const name = "AC/DC"; // usually from user input, parameterized

const sql = await db.from.artists
.sql`SELECT * FROM Artist WHERE Name = ${name}`.toArray();

It is a useful escape hatch for when you need to execute a query that is not supported by the Verse query API.

sum​

The sum operator is an aggregate operator that calculates the sum of a sequence of numbers:

let sum = await db.from.artists.select(a => a.artistId).sum();

There is a shorthand for the common case above:

sum = await db.from.artists.sum(a => a.artistId);

toArray​

Buffers the sequence into an array:

const toArray = await db.from.artists.toArray();

By default, sequences are lazy and will not execute until the query is iterated, or a terminal operator like toArray is called.

where​

The where operator is used to filter elements in a sequence:

const where = await db.from.artists.where(a => a.name === "AC/DC").toArray();

with​

The with operator is used to specify one or more navigation properties that should be eager loaded:

let eager = db.from.artists.limit(1).with(a => a.albums);

for await (const artist of eager) {
console.log(artist);
}

See the Eager Loading section for more information.