Reference
WHERE Operators
Full reference for filter operators available in Jazz query builders, with examples for each column kind.
Operator reference by column type
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 |
Examples
Equality and inequality
// Exact match (shorthand — no operator object needed)
const incompleteTodos = await db.all(app.todos.where({ done: false }));
// Not equal
const nonDraftTodos = await db.all(app.todos.where({ title: { ne: "Draft" } }));
// One of a set
const selectedTodos = await db.all(app.todos.where({ id: { in: [todoIdA, todoIdB] } }));// Exact match
let query = QueryBuilder::new("todos")
.filter_eq("done", Value::Boolean(false))
.build();
let incomplete_todos = client.query(query, None).await?;
// Not equal
let query = QueryBuilder::new("todos")
.filter_ne("title", Value::Text("Draft".into()))
.build();
let non_draft_todos = client.query(query, None).await?;Numeric comparisons
const oneWeekAgo = Date.now() - 7 * 24 * 60 * 60 * 1000;
const recentTodos = await db.all(app.todos.where({ created_at: { gt: oneWeekAgo } }));
const highPriority = await db.all(app.todos.where({ priority: { gte: 3 } }));
const lowPriority = await db.all(app.todos.where({ priority: { lt: 10 } }));let now_ms = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.unwrap()
.as_millis() as u64;
let one_week_ago = Value::Timestamp(now_ms - 7 * 24 * 60 * 60 * 1000);
let query = QueryBuilder::new("todos")
.filter_gt("created_at", one_week_ago)
.build();
let recent_todos = client.query(query, None).await?;
let query = QueryBuilder::new("todos")
.filter_ge("priority", Value::Integer(3))
.build();
let high_priority = client.query(query, None).await?;
let query = QueryBuilder::new("todos")
.filter_lt("priority", Value::Integer(10))
.build();
let low_priority = client.query(query, None).await?;String contains
// Substring match (case-sensitive)
const matches = await db.all(app.todos.where({ title: { contains: searchTerm } }));// Substring match (case-sensitive)
let query = QueryBuilder::new("todos")
.filter_contains("title", Value::Text(search_term.into()))
.build();
let matches = client.query(query, None).await?;Null checks on optional references
// Rows where the optional ref is not set
const unlinkedTodos = await db.all(app.todos.where({ parentId: { isNull: true } }));
// Rows where it is set
const linkedTodos = await db.all(app.todos.where({ parentId: { isNull: false } }));// Rows where the optional ref is not set
let query = QueryBuilder::new("todos").filter_is_null("parent").build();
let unlinked_todos = client.query(query, None).await?;
// Rows where it is set
let query = QueryBuilder::new("todos")
.filter_is_not_null("parent")
.build();
let linked_todos = client.query(query, None).await?;Multiple conditions (AND)
All predicates passed to where(...) / chained filter_* calls are AND-combined:
// done AND assigned to a project
const doneWithProject = await db.all(
app.todos.where({
done: true,
projectId: { isNull: false },
}),
);// Multiple filter calls are AND-combined
let query = QueryBuilder::new("todos")
.filter_eq("done", Value::Boolean(true))
.filter_is_not_null("project")
.build();
let done_with_project = client.query(query, None).await?;Combining with ordering and limits
const recentIncomplete = await db.all(
app.todos.where({ done: false }).orderBy("created_at", "asc").limit(50),
);let query = QueryBuilder::new("todos")
.filter_eq("done", Value::Boolean(false))
.order_by("created_at")
.limit(50)
.build();
let recent_incomplete = client.query(query, None).await?;Live subscriptions with WHERE
useAll and query subscriptions accept the same query builders as db.all. The subscription stays active and updates whenever any row enters or exits the filter:
export function subscribeOpenTodos(db: Db, onChange: (todos: unknown[]) => void) {
return db.subscribeAll(app.todos.where({ done: false }), ({ all }) => onChange(all));
}let query = QueryBuilder::new("todos")
.filter_eq("done", Value::Boolean(false))
.build();
let pending = client.subscribe(query).await?;For reactive framework bindings (useAll in React/Vue, QuerySubscription in Svelte), see Framework Patterns.