Logical Operators
Combine multiple conditions with AND and OR logic.
| Form | Where shape | SQL |
|---|---|---|
| Implicit AND | multiple keys in one object | AND between each key |
| Explicit AND | { and: [...] } | AND between grouped clauses |
| OR | { or: [...] } | OR between grouped clauses |
| NOT | { field: { not: ... } } | NOT (...) around the negated condition |
Implicit AND
Multiple conditions in the same object combine with AND.
{ where: { status: 'active', role: 'admin', verified: true } }
// SQL: WHERE "status" = 'active' AND "role" = 'admin' AND "verified" = trueExplicit AND
Use an and array to group conditions explicitly.
{
where: {
and: [
{ status: 'active' },
{ role: { in: ['admin', 'moderator'] } },
]
}
}
// SQL: WHERE ("status" = 'active') AND ("role" IN ('admin', 'moderator'))OR
Use an or array to match any of several conditions.
{
where: {
or: [
{ status: 'active' },
{ isPublished: true },
]
}
}
// SQL: WHERE ("status" = 'active') OR ("is_published" = true)NOT
not negates whatever it wraps: a bare value negates eq, a nested operator object negates that operator.
{ where: { status: { not: 'archived' } } }
// SQL: WHERE NOT ("status" = 'archived')
{ where: { views: { not: { gt: 100 } } } }
// SQL: WHERE NOT ("views" > 100)NOTE
not is supported on the PostgreSQL connector. The dedicated negation operators below are often clearer for a single condition.
Dedicated Negation Operators
| Operator | Example | SQL |
|---|---|---|
ne / neq | { status: { ne: 'deleted' } } | != |
nin | { status: { nin: ['deleted', 'banned'] } } | NOT IN |
nlike | { email: { nlike: '%@test.com' } } | NOT LIKE |
nilike | { email: { nilike: '%@test.com' } } | NOT ILIKE |
isn / ne: null | { verifiedAt: { isn: null } } | IS NOT NULL |
notBetween | { score: { notBetween: [40, 60] } } | NOT BETWEEN |
NOTE
ne/neq/nin follow SQL three-valued logic - a row whose field is NULL never matches them (NULL <> value is UNKNOWN, not TRUE). Use exists/notExists or an explicit { field: null } branch to include NULL rows.
Nested AND/OR
Combine AND and OR for multi-level logic.
// (status = 'active' AND verified = true) OR (role = 'admin')
{
where: {
or: [
{ and: [{ status: 'active' }, { verified: true }] },
{ role: 'admin' },
]
}
}A top-level key alongside or ANDs with it - these two filters are equivalent:
// status = 'active' AND (role = 'admin' OR role = 'moderator')
{ where: { status: 'active', or: [{ role: 'admin' }, { role: 'moderator' }] } }
// Same result, using in instead
{ where: { status: 'active', role: { in: ['admin', 'moderator'] } } }Empty Groups
An empty and/or array is not a no-op - each resolves to what the operator means with zero conditions.
{ where: { and: [] } }
// Vacuously TRUE - dropped from the query entirely, no condition added
{ where: { or: [] } }
// SQL: WHERE false - vacuously FALSE, matches nothingNOTE
This matters for a caller-built list, e.g. { or: permittedOrgIds.map(id => ({ orgId: id })) }: an empty permission list must return zero rows, so or: [] matching nothing is the safe default.
See also
- Filter System Overview - the
filtershape and the fullwhereoperator table - Null Operators -
isn, one of the dedicated negation operators above - Comparison Operators -
ne/neq, the other dedicated negation operators - Quick Reference - every operator, one line each
Files:
packages/connectors/src/relational/core/repositories/dialect/filter.ts-FilterBuilder,buildLogicalGroupCondition/buildNotConditionpackages/connectors/src/relational/postgres/repositories/dialect/query.ts-PostgresQueryOperators.FNS, per-operator SQL builderspackages/filter/src/common/operators.ts-QueryOperatorsconstants