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 kindOperators / shape
ideq, 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())
}

On this page