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.
orderBy()
Section titled “orderBy()”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();Parameters
Section titled “Parameters”.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") |
Single Field
Section titled “Single Field”// Function syntax.orderBy((ctx) => ctx.p.name, "asc")
// Alias syntax.orderBy("p", "name", "asc")Multiple Fields
Section titled “Multiple Fields”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" },])Null Handling
Section titled “Null Handling”Control where null values appear:
.orderBy((ctx) => ({ field: ctx.p.email, direction: "asc", nulls: "last", // or "first"}))Ordering by Edge Properties
Section titled “Ordering by Edge Properties”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();Ordering Aggregated Results
Section titled “Ordering Aggregated Results”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();limit()
Section titled “limit()”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();Parameters
Section titled “Parameters”.limit(n)| Parameter | Type | Description |
|---|---|---|
n | number | Maximum number of results to return |
offset()
Section titled “offset()”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();Parameters
Section titled “Parameters”.offset(n)| Parameter | Type | Description |
|---|---|---|
n | number | Number of results to skip |
Simple Pagination with limit/offset
Section titled “Simple Pagination with limit/offset”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();}
// Usageconst page1 = await getPage(1, 20); // Results 1-20const page2 = await getPage(2, 20); // Results 21-40Note: For large datasets, use cursor pagination instead. Offset-based pagination becomes slower as offset increases.
Ordering Requirements
Section titled “Ordering Requirements”For Pagination
Section titled “For Pagination”Both paginate() and stream() require an orderBy() clause:
// Required for paginationconst page = await store .query() .from("Person", "p") .select((ctx) => ctx.p) .orderBy("p", "name", "asc") // Required .paginate({ first: 20 });
// Required for streamingconst stream = store .query() .from("Event", "e") .select((ctx) => ctx.e) .orderBy("e", "createdAt", "desc") // Required .stream();Stable Ordering
Section titled “Stable Ordering”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 equalReal-World Examples
Section titled “Real-World Examples”Leaderboard
Section titled “Leaderboard”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();Recent Activity Feed
Section titled “Recent Activity Feed”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();Paginated Search Results
Section titled “Paginated Search Results”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();}