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, in
s.boolean()eq, ne, in
s.int() / s.float()eq, ne, gt, gte, lt, lte, in
s.timestamp()eq, ne, gt, gte, lt, lte, in
s.bytes()eq, ne, in
s.uuid() (required)eq, ne, in
s.uuid().optional()eq, ne, in, isNull
s.enum(...)eq, ne, in
s.array(...)eq, contains, in
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 = Query::from("todos").filter(eq(col("done"), lit(false)));

    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 = Query::from("todos")
        .filter(eq(col("done"), lit(false)))
        .order_by("title", OrderDirection::Asc);

    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 them with a deterministic order. If the first sort column is not unique, add orderBy("id") as the final tie-breaker 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")
      .orderBy("id", "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 = Query::from("todos")
        .filter(eq(col("done"), lit(false)))
        .order_by("title", OrderDirection::Asc)
        .order_by("id", OrderDirection::Asc)
        .limit(page_size)
        .offset(offset);

    let rows = client.query(query, None).await?;
    Ok(rows.len())
}

On this page