Skip to content

Order

Order operations control how results are sorted and how many are returned. Use orderBy() for sorting, limit() to cap results, and offset() for simple pagination.

Sort results by one or more fields:

const sorted = await store
.query()
.from("Person", "p")
.select((ctx) => ctx.p)
.orderBy((ctx) => ctx.p.name, "asc")
.execute();
.orderBy(fieldSelector, direction?)
.orderBy(alias, field, direction?)
ParameterTypeDescription
fieldSelector(ctx) => fieldFunction that selects the field to sort by
aliasstringNode/edge alias (alternative syntax)
fieldstringField name (alternative syntax)
direction"asc" | "desc"Sort direction (default: "asc")
// Function syntax
.orderBy((ctx) => ctx.p.name, "asc")
// Alias syntax
.orderBy("p", "name", "asc")

Chain orderBy() for multi-field sorting:

const sorted = await store
.query()
.from("Task", "t")
.select((ctx) => ctx.t)
.orderBy("t", "priority", "desc") // Primary sort
.orderBy("t", "createdAt", "asc") // Secondary sort
.execute();

Or use the array syntax:

.orderBy((ctx) => [
{ field: ctx.t.priority, direction: "desc" },
{ field: ctx.t.createdAt, direction: "asc" },
])

Control where null values appear:

.orderBy((ctx) => ({
field: ctx.p.email,
direction: "asc",
nulls: "last", // or "first"
}))

Order by properties on traversed edges:

const employees = await store
.query()
.from("Company", "c")
.traverse("worksAt", "e", { direction: "in" })
.to("Person", "p")
.select((ctx) => ({
name: ctx.p.name,
startDate: ctx.e.startDate,
}))
.orderBy("e", "startDate", "desc") // Most recent hires first
.execute();

Order by aggregate values:

import { count, field } from "@nicia-ai/typegraph";
const topDepartments = await store
.query()
.from("Employee", "e")
.groupBy("e", "department")
.aggregate({
department: field("e", "department"),
headcount: count("e"),
})
.orderBy((ctx) => ctx.headcount, "desc")
.execute();

Cap the number of results returned:

const top10 = await store
.query()
.from("Person", "p")
.select((ctx) => ctx.p)
.orderBy("p", "score", "desc")
.limit(10)
.execute();
.limit(n)
ParameterTypeDescription
nnumberMaximum number of results to return

Skip a number of results (useful for simple pagination):

const page2 = await store
.query()
.from("Person", "p")
.select((ctx) => ctx.p)
.orderBy("p", "name", "asc")
.limit(10)
.offset(10) // Skip first 10 results
.execute();
.offset(n)
ParameterTypeDescription
nnumberNumber of results to skip
async function getPage(pageNumber: number, pageSize: number) {
return store
.query()
.from("Person", "p")
.select((ctx) => ctx.p)
.orderBy("p", "name", "asc")
.limit(pageSize)
.offset((pageNumber - 1) * pageSize)
.execute();
}
// Usage
const page1 = await getPage(1, 20); // Results 1-20
const page2 = await getPage(2, 20); // Results 21-40

Note: For large datasets, use cursor pagination instead. Offset-based pagination becomes slower as offset increases.

Both paginate() and stream() require an orderBy() clause:

// Required for pagination
const page = await store
.query()
.from("Person", "p")
.select((ctx) => ctx.p)
.orderBy("p", "name", "asc") // Required
.paginate({ first: 20 });
// Required for streaming
const stream = store
.query()
.from("Event", "e")
.select((ctx) => ctx.e)
.orderBy("e", "createdAt", "desc") // Required
.stream();

For deterministic pagination, include a unique field (like id) in your ordering:

.orderBy("p", "name", "asc")
.orderBy("p", "id", "asc") // Ensures stable ordering when names are equal
const leaderboard = await store
.query()
.from("Player", "p")
.select((ctx) => ({
name: ctx.p.name,
score: ctx.p.score,
}))
.orderBy("p", "score", "desc")
.limit(100)
.execute();
const feed = await store
.query()
.from("Activity", "a")
.whereNode("a", (a) => a.userId.eq(currentUserId))
.select((ctx) => ctx.a)
.orderBy("a", "createdAt", "desc")
.limit(50)
.execute();
async function searchProducts(query: string, page: number) {
const pageSize = 20;
return store
.query()
.from("Product", "p")
.whereNode("p", (p) => p.name.ilike(`%${query}%`))
.select((ctx) => ({
id: ctx.p.id,
name: ctx.p.name,
price: ctx.p.price,
}))
.orderBy("p", "relevance", "desc")
.orderBy("p", "id", "asc")
.limit(pageSize)
.offset((page - 1) * pageSize)
.execute();
}
  • Execute - Cursor pagination and streaming
  • Shape - Output transformation
  • Filter - Reducing results with predicates