Logical Operators
Combine multiple conditions with AND and OR logic.
Implicit AND
Multiple conditions in the same object are combined with AND:
{
where: {
status: 'active',
role: 'admin',
verified: true,
}
}
// SQL: WHERE "status" = 'active' AND "role" = 'admin' AND "verified" = trueExplicit AND
Use and array for explicit AND conditions:
{
where: {
and: [
{ status: 'active' },
{ role: { in: ['admin', 'moderator'] } },
{ createdAt: { gte: new Date('2024-01-01') } },
]
}
}
// SQL: WHERE ("status" = 'active')
// AND ("role" IN ('admin', 'moderator'))
// AND ("created_at" >= '2024-01-01')OR Operator
Use or array for OR conditions:
{
where: {
or: [
{ status: 'active' },
{ isPublished: true },
{ featured: true },
]
}
}
// SQL: WHERE ("status" = 'active')
// OR ("is_published" = true)
// OR ("featured" = true)Nested AND/OR
Combine AND and OR for complex logic:
// (status = 'active' AND verified = true) OR (role = 'admin')
{
where: {
or: [
{
and: [
{ status: 'active' },
{ verified: true },
]
},
{ role: 'admin' },
]
}
}
// status = 'active' AND (role = 'admin' OR role = 'moderator')
{
where: {
status: 'active',
or: [
{ role: 'admin' },
{ role: 'moderator' },
]
}
}
// Equivalent to:
{
where: {
status: 'active',
role: { in: ['admin', 'moderator'] },
}
}Empty Groups
An empty and/or array is not a no-op -- each empty case resolves to what the operator means with zero conditions:
// Empty AND is vacuously TRUE - dropped from the query entirely
{ where: { and: [] } }
// SQL: (no condition added)
// Empty OR is vacuously FALSE - compiles to a condition that matches nothing
{ where: { or: [] } }
// SQL: WHERE falseThis matters when the array is built from a caller-supplied list, e.g. { or: permittedOrgIds.map(id => ({ orgId: id })) }: an empty permission list must return zero rows, not every row, so or: [] matching nothing is the safe default.
NOT Logic
IGNIS has a general-purpose not operator that negates whatever condition it wraps - a bare value negates eq, and a nested operator object negates that operator. It is supported on the PostgreSQL connector:
// NOT equal (bare value negates eq)
{ where: { status: { not: 'archived' } } }
// SQL: WHERE NOT ("status" = 'archived')
// Negate a nested operator condition
{ where: { views: { not: { gt: 100 } } } }
// SQL: WHERE NOT ("views" > 100)The dedicated negation operators remain available and are often clearer for a single condition:
// NOT equal
{ where: { status: { ne: 'deleted' } } }
{ where: { status: { neq: 'deleted' } } }
// NOT IN
{ where: { status: { nin: ['deleted', 'banned'] } } }
// NOT LIKE
{ where: { email: { nlike: '%@test.com' } } }
// NOT ILIKE
{ where: { email: { nilike: '%@test.com' } } }
// IS NOT NULL
{ where: { verifiedAt: { isn: null } } }
{ where: { verifiedAt: { ne: null } } }
// NOT BETWEEN
{ where: { score: { notBetween: [40, 60] } } }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 when you need NULL rows in the result.
Complex Example
// Find active products that are either:
// - Featured with high rating, OR
// - On sale with good stock
{
where: {
status: 'active',
deletedAt: { is: null },
or: [
{
and: [
{ featured: true },
{ rating: { gte: 4.5 } }
]
},
{
and: [
{ onSale: true },
{ stock: { gte: 10 } }
]
}
]
}
}See also
- Filter System Overview - the
filtershape and the fullwhereoperator table - Null Operators -
isn, one of the dedicated negation operators referenced above - Comparison Operators -
ne/neq, the other dedicated negation operators - Quick Reference - every operator, one line each
Files:
packages/core/src/connectors/postgres/repositories/dialect/filter.ts-FilterBuilder,buildLogicalGroupCondition/buildNotConditionpackages/core/src/connectors/postgres/repositories/dialect/query.ts-PostgresQueryOperators.FNS, per-operator SQL builderspackages/core/src/base/repositories/common/operators.ts-QueryOperatorsconstants