Filters
Advanced filtering and query operators
Filters
The where clause allows you to filter records with powerful operators. All filters are type-safe and composable.
Basic Filtering
equals
Match exact values:
// String equality
const users = await collections.users.findMany({
where: {
status: { equals: 'active' }
}
})
// Number equality
const posts = await collections.posts.findMany({
where: {
views: { equals: 1000 }
}
})
// Boolean equality
const publishedPosts = await collections.posts.findMany({
where: {
published: { equals: true }
}
})not
Invert a condition:
// Not equal
const users = await collections.users.findMany({
where: {
status: { not: 'inactive' }
}
})
// Not null
const usersWithEmail = await collections.users.findMany({
where: {
email: { not: null }
}
})Comparison Operators
Number Comparisons
const posts = await collections.posts.findMany({
where: {
views: {
gt: 100 // Greater than
}
}
})
const posts = await collections.posts.findMany({
where: {
views: {
gte: 100 // Greater than or equal
}
}
})
const posts = await collections.posts.findMany({
where: {
views: {
lt: 1000 // Less than
}
}
})
const posts = await collections.posts.findMany({
where: {
views: {
lte: 1000 // Less than or equal
}
}
})Available comparison operators:
Prop
Type
String Operators
contains
Substring match (case-sensitive):
const posts = await collections.posts.findMany({
where: {
title: { contains: 'tutorial' }
}
})startsWith
Match strings starting with a value:
const users = await collections.users.findMany({
where: {
email: { startsWith: 'admin' }
}
})endsWith
Match strings ending with a value:
const users = await collections.users.findMany({
where: {
email: { endsWith: '@example.com' }
}
})Array Operators
in
Match any value in an array:
const users = await collections.users.findMany({
where: {
status: { in: ['active', 'pending'] }
}
})notIn
Exclude values in an array:
const users = await collections.users.findMany({
where: {
status: { notIn: ['deleted', 'banned'] }
}
})isEmpty
Check if array field is empty:
const posts = await collections.posts.findMany({
where: {
tags: { isEmpty: true }
}
})has
Check if array contains a value:
const posts = await collections.posts.findMany({
where: {
tags: { has: 'typescript' }
}
})hasSome
Check if array contains any of the values:
const posts = await collections.posts.findMany({
where: {
tags: { hasSome: ['typescript', 'javascript'] }
}
})hasEvery
Check if array contains all values:
const posts = await collections.posts.findMany({
where: {
tags: { hasEvery: ['typescript', 'nodejs'] }
}
})Null Checks
isNull
Match null values:
const users = await collections.users.findMany({
where: {
bio: { isNull: true }
}
})isNotNull
Match non-null values:
const users = await collections.users.findMany({
where: {
bio: { isNotNull: true }
}
})Date Operators
before/after
Filter dates:
const recentPosts = await collections.posts.findMany({
where: {
createdAt: { after: new Date('2024-01-01') }
}
})
const oldPosts = await collections.posts.findMany({
where: {
createdAt: { before: new Date('2023-01-01') }
}
})Date Comparisons
const posts = await collections.posts.findMany({
where: {
createdAt: {
gte: new Date('2024-01-01'),
lt: new Date('2024-02-01')
}
}
})Logical Operators
AND
All conditions must be true (default behavior):
const users = await collections.users.findMany({
where: {
AND: [
{ status: { equals: 'active' } },
{ age: { gte: 18 } },
{ country: { equals: 'US' } }
]
}
})Shorthand (multiple conditions):
const users = await collections.users.findMany({
where: {
status: { equals: 'active' },
age: { gte: 18 },
country: { equals: 'US' }
}
})OR
At least one condition must be true:
const posts = await collections.posts.findMany({
where: {
OR: [
{ title: { contains: 'typescript' } },
{ title: { contains: 'javascript' } },
{ title: { contains: 'nodejs' } }
]
}
})NOT
Invert conditions:
const users = await collections.users.findMany({
where: {
NOT: {
status: { equals: 'deleted' }
}
}
})Combining Logical Operators
const posts = await collections.posts.findMany({
where: {
AND: [
{ published: { equals: true } },
{
OR: [
{ title: { contains: 'tutorial' } },
{ tags: { has: 'beginner' } }
]
}
]
}
})Nested Filters
Filter on nested object fields:
const users = await collections.users.findMany({
where: {
'settings.theme': { equals: 'dark' },
'settings.notifications.email': { equals: true }
}
})Relation Filters
Filter based on related records:
Complex Examples
Advanced Search
const searchPosts = async (query: string, tags?: string[]) => {
return await collections.posts.findMany({
where: {
published: { equals: true },
OR: [
{ title: { contains: query } },
{ content: { contains: query } }
],
...(tags && {
tags: { hasEvery: tags }
})
},
orderBy: {
createdAt: 'desc'
}
})
}Date Range
const getPostsInRange = (start: Date, end: Date) => {
return collections.posts.findMany({
where: {
createdAt: {
gte: start,
lte: end
}
}
})
}Filter by Computed Fields
// Find popular posts (high views and recent)
const popularPosts = await collections.posts.findMany({
where: {
AND: [
{ views: { gte: 1000 } },
{ createdAt: { after: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000) } }
]
}
})Performance Tips
- Use indexes on frequently filtered fields
- Use specific operators when possible (e.g.,
equalsovercontains) - Limit OR conditions - they can be slow
- Use pagination with filters to avoid large result sets
- Consider database indexes for complex filters
// In your collection definition
export const users = collection({
slug: 'users',
fields: {
email: field({
type: email(),
indexed: true // Add index for filtering
}),
status: field({
type: enumField(['active', 'inactive']),
indexed: true // Add index for filtering
})
}
})Operator Reference
Prop
Type
Next Steps
- Queries - Basic CRUD operations
- Querying Relations - Filter by related records
- Pagination - Pagination and sorting strategies