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 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

Nullable columns with ordinary filter operators also support isNull. Required columns, id, and payload enums do not expose it.

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] } }));

Numeric comparisons

const oneWeekAgo = Date.now() - 7 * 24 * 60 * 60 * 1000;
​
const recentTodos = await db.all(app.todos.where({ $createdAt: { gt: oneWeekAgo } }));
const highPriority = await db.all(app.todos.where({ priority: { gte: 3 } }));
const lowPriority = await db.all(app.todos.where({ priority: { lt: 10 } }));

String contains

// Substring match (case-sensitive)
const matches = await db.all(app.todos.where({ title: { contains: searchTerm } }));

Null checks on optional columns

In TypeScript, isNull: true matches missing values and isNull: false matches present values. Nullable columns with ordinary filter operators support it, including scalar and array columns, not just references; required columns and payload enums do not expose it.

// 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 } }));

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 },
}),
);

Combining with ordering and limits

const recentIncomplete = await db.all(
app.todos.where({ done: false }).orderBy("$createdAt", "asc").limit(50),
);

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.subscribe(app.todos.where({ done: false }), (todos) => onChange(todos));
}

For reactive framework bindings (useAll in React/Vue/Solid, QuerySubscription in Svelte), see Framework Patterns.