Operators
Query `where` operators and mutation filter helpers (Drizzle-style)
Query where (Object Filters)
Object filters are the primary query mechanism for ORM relational queries. You can combine equality checks, comparison operators, and logical combinators in a single where object.
Combine equality checks, comparison operators, and logical combinators in a single where object:
await db.query.users.findMany({
where: {
OR: [{ role: 'admin' }, { role: 'member' }],
age: { gt: 18 },
},
});For the full list of supported operators, see API Reference below.
String Operators (post-fetch)
The ORM supports Drizzle-style like/ilike operators and evaluates them post-fetch.
Search for posts containing "javascript" (case-insensitive):
await db.query.posts.withIndex('by_title').findMany({
where: { title: { ilike: '%javascript%' } },
});You can also use convenience operators for common patterns:
await db.query.users.withIndex('by_email').findMany({
where: { email: { endsWith: '@example.com' } },
});The supported string operators are:
like,ilike,notLike,notIlikestartsWith,endsWith,contains
Array Operators (post-fetch)
If a field is an array (for example, embeddings or other array-like values), you can use:
arrayContainsarrayContainedarrayOverlaps
Mutation where (Filter Expressions)
Mutation builders (insert, update, delete) use operator helpers that return a FilterExpression. These helpers accept column builders (like users.role) and use builder typing to infer the right value type.
Update all users with a specific role who are over 18:
import { and, eq, gt } from 'kitcn/orm';
// Schema: index('by_role').on(t.role) on users table
await ctx.orm.update(users).set({ role: 'admin' }).where(
and(
eq(users.role, 'member'),
gt(users.age, 18),
)
);For the full list of mutation/RLS helpers, see API Reference below.
Unsupported SQL-only Features
These SQL-specific features are not available in the ORM:
RAWfilters and SQL placeholders (sql.placeholder(...))- Prepared statements
- SQL subquery operators
exists/notExists(Convex has no SQL subquery runtime)
For existence checks, use relation filters instead:
// Users with posts
await db.query.users.findMany({
where: { posts: true },
});
// Users without posts
await db.query.users.findMany({
where: { NOT: { posts: true } },
});API Reference
Supported Operators
Full list of operators available inside a where object:
where: {
OR: [],
AND: [],
NOT: {},
// relations (filter by existence or nested filters)
posts: true,
// columns
age: 15,
age: { eq: 15 },
age: { ne: 15 },
age: { gt: 15 },
age: { gte: 15 },
age: { lt: 15 },
age: { lte: 15 },
age: { between: [18, 65] },
age: { notBetween: [18, 65] },
role: { in: ['admin', 'member'] },
role: { notIn: ['banned'] },
email: { isNull: true },
email: { isNotNull: true },
}Note: between is inclusive (>= min and <= max). notBetween is strict outside-range (< min or > max).
Common Helpers
All available mutation/RLS operator helpers:
| Category | Helpers |
|---|---|
| Comparison | eq, ne, gt, gte, lt, lte |
| Range | between, notBetween |
| Set | inArray, notInArray |
| Logical | and, or, not |
| Null | isNull, isNotNull |