Reading Data
Filters, Sorting & Pagination
Filter rows with where(), sort with orderBy(), and paginate with limit/offset.
Filters
Use where(...) to filter rows. Pass the columns you want to match on — all conditions are combined with AND. OR filters are not supported in queries; use multiple queries if you need disjoint result sets.
Operator support by column type (TypeScript):
| Column kind | Operators / shape |
|---|---|
id | eq, ne, in |
s.string() | eq, ne, contains |
s.boolean() | plain boolean equality (done: true) |
s.int() / s.float() | eq, ne, gt, gte, lt, lte |
s.timestamp() | eq, ne, gt, gte, lt, lte |
s.bytes() | eq, ne |
s.ref("...") (required) | eq, ne |
s.ref("...").optional() | eq, ne, isNull |
s.enum(...) | eq, ne, in |
s.array(...) | eq, contains |
s.json() / s.json(schema) | eq, ne, in |
export async function readTodosWithFilters(db: Db) {
return db.all(app.todos.where({ done: false, title: { contains: "docs" } }));
}export async function readTodosWithWhereOperators(db: Db) {
await db.all(app.todos.where({ done: false }));
await db.all(app.todos.where({ title: { contains: "milk" } }));
await db.all(app.todos.where({ projectId: { ne: EXAMPLE_PROJECT_ID } }));
}pub async fn read_todos_with_filters(client: &JazzClient) -> jazz_tools::Result<usize> {
let query = QueryBuilder::new("todos")
.filter_eq("done", Value::Boolean(false))
.build();
let rows = client.query(query, None).await?;
Ok(rows.len())
}Sorting
Sort results with orderBy(...). Pass a column name and optionally "asc" or "desc".
Always sort before paginating. Unsorted items may not appear on the same page across all queries.
export async function readTodosSortedByTitle(db: Db) {
return db.all(app.todos.where({ done: false }).orderBy("title", "asc"));
}pub async fn read_todos_sorted(client: &JazzClient) -> jazz_tools::Result<usize> {
let query = QueryBuilder::new("todos")
.filter_eq("done", Value::Boolean(false))
.order_by("title")
.build();
let rows = client.query(query, None).await?;
Ok(rows.len())
}Pagination
limit(n) caps the number of rows returned; offset(n) skips that many rows. Combine with a deterministic orderBy(...) so page boundaries are stable.
export async function readTodoPage(db: Db, page: number, pageSize = 20) {
const offset = Math.max(0, (page - 1) * pageSize);
return db.all(
app.todos.where({ done: false }).orderBy("title", "asc").limit(pageSize).offset(offset),
);
}pub async fn read_todo_page(
client: &JazzClient,
page_size: usize,
page: usize,
) -> jazz_tools::Result<usize> {
let offset = page.saturating_sub(1) * page_size;
let query = QueryBuilder::new("todos")
.filter_eq("done", Value::Boolean(false))
.order_by("title")
.limit(page_size)
.offset(offset)
.build();
let rows = client.query(query, None).await?;
Ok(rows.len())
}