Skip to content

orderBy sorts the entities a query matches by one attribute, and the order holds across every page. You build the sort key with asc or desc from @arkiv-network/sdk/query, and through a schema the key is checked against its columns. The examples on this page use the Posts schema and clients from your first entity.

import { desc } from "@arkiv-network/sdk/query"
const { entities } = await publicClient
.select({ $key: true, title: true, score: true })
.from(Posts)
.ownedBy(account.address)
.orderBy(desc("score"))
.limit(10)
.fetch()

desc sorts largest first, and asc sorts smallest first. Through a schema, a key takes its type from the column, so desc("score") sorts score as a dec.

A column doesn’t need .indexed() to be sorted on: asc("title") works, though title isn’t indexed. Only bytes columns can’t be sorted on.

Values sort in the order they compare in conditions. Numbers and decimals sort by value, and false comes before true. Strings, addresses and keys sort byte by byte, so strings sort by their UTF-8 bytes, not alphabetically.

The node sorts by one attribute, so orderBy takes one key. Entities that tie on it come in the node’s own order, and so do all entities without orderBy. Calling orderBy again replaces the key.

The four entity fields you can filter on can also be sorted on: $key, $owner, $creator and $expiresAt. Each has a fixed type, so its key needs nothing more. To list an account’s entities by when they expire, soonest first:

import { asc } from "@arkiv-network/sdk/query"
const { entities } = await publicClient
.select({ $key: true, $expiresAt: true })
.ownedBy(account.address)
.orderBy(asc("$expiresAt"))
.fetch()

$createdAt and $updatedAt can’t be sorted on. Select them and sort the rows in JavaScript instead.

An entity that doesn’t have the key’s attribute, or holds it with another type, has no value to sort by. It sorts below every value: first with asc, last with desc.

This covers an optional column an entity leaves unset. Arkiv is public, so it also covers an entity another project wrote with your schema’s tag but without the column.

To leave those entities out, add hasType with the key’s attribute and type to the condition. It matches only the entities that hold the attribute with that type.

Through a schema, a key must name a column that isn’t bytes, or one of the four entity fields, and use its type. Anything else is a compile error, and throws InvalidPredicateError if it runs anyway:

const posts = publicClient.select({ $key: true }).from(Posts)
posts.orderBy(asc("body")) // bytes can’t be sorted on
posts.orderBy(desc("views")) // views isn’t a column
posts.orderBy(desc("score", "u256")) // score is a dec
posts.orderBy(desc("$createdAt")) // $createdAt can’t be sorted on
posts.orderBy(asc("category"), desc("score")) // one key only

The compiler checks the key against the schema the query has when you call orderBy. Call it after from: a key passed before from is only checked when the query runs.

A query without a schema has no column to take a type from. Write the type as the second argument, the same type the attribute was written with:

import { desc, eq } from "@arkiv-network/sdk/query"
const { entities } = await publicClient
.select({ $key: true, score: true })
.where(eq("category", "news"))
.orderBy(desc("score", "dec"))
.fetch()

A key without a type is a compile error here. Entities that hold score with another type sort as if they didn’t have it, so this desc sort puts them last.

query() takes the same key as its orderBy option, checked the same way:

import { desc, eq } from "@arkiv-network/sdk/query"
const page = await publicClient.query(eq("category", "news"), {
select: { $key: true, score: true },
orderBy: desc("score", "dec"),
})

The order covers every match, not each page on its own. With the same orderBy on every request, offset pages through one order. Without orderBy, matches come oldest first.

toString() shows the sort as an ORDER BY clause at the end of the query language text:

const query = publicClient
.select({ $key: true })
.from(Posts)
.orderBy(desc("score"))
console.log(query.toString())

This prints:

arkiv.schema = str('my-app.posts') ORDER BY score:dec DESC