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?)
Parameter Type Description
fieldSelector (ctx) => field Function that selects the field to sort by
alias string Node/edge alias (alternative syntax)
field string Field 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();

Aggregate queries have their own orderBy(key, direction?), called after .aggregate({...}). key is any output name from the fields object — a grouped field or an aggregate alias:

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("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)
Parameter Type Description
n number Maximum 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)
Parameter Type Description
n number Number 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