Skip to main content

Filtering

Filtering in nestjs-query has an object based syntax.

For a full reference of filter operations see filter reference

The following example filters for all todoItems that are marked completed.

{
todoItems(filter: {completed: {is: true}}){
pageInfo{
hasNextPage
hasPreviousPage
startCursor
endCursor
}
edges{
node{
id
title
completed
created
updated
}
cursor
}
}
}

Setting the generated filter-type depth

When querying the default filter is one level deep. You can specify the generated filter-type depth by using the QueryOptions decorator on your DTO.

You can find the documentation and an example in the QueryOptions reference.

Setting a default filter

When querying the default filter is empty. You can specify a default filter by using the QueryOptions decorator on your DTO.

You can find the documentation and an example in the QueryOptions reference.

Setting allowed boolean expressions

When filtering you can provide and and or expressions to provide advanced filtering. You can turn off either by using the QueryOptions decorator on your DTO.

You can find the documentation and an example in the QueryOptions reference.

How Filters Are Applied

Filters in nestjs-query come from multiple sources and combine differently depending on the source.

Filter Sources

SourceWhen AppliedHow Combined
User filter (GraphQL args)AlwaysBase filter
Default filter (@QueryOptions)Only when user provides NO filterReplaces empty filter
Auth filter (@Authorize)AlwaysANDed with user filter

Default Filter Behavior

The defaultFilter from @QueryOptions is used as the GraphQL field's defaultValue. This means:

  • ✅ If user provides NO filter → defaultFilter is used
  • ❌ If user provides ANY filter → defaultFilter is completely ignored
@QueryOptions({ defaultFilter: { archived: { is: false } } })
warning

Default filter is NOT merged - it's a fallback. Use authorization for filters that must always apply.

Authorization Filter Behavior

Filters from @Authorize are always merged with the user's filter using AND logic:

// User query
filter: { title: { like: '%todo%' } }

// @Authorize returns
{ ownerId: { eq: currentUserId } }

// Actual filter applied
{ and: [{ title: { like: '%todo%' } }, { ownerId: { eq: currentUserId } }] }

For more details, see Authorization.

Filter Flow

GraphQL Query (filter arg)

Default filter applied if user filter empty

Resolver receives query

Auth filter merged (AND)

QueryService.query()

ORM (TypeORM/Sequelize/Mongoose)

Database

Relation Filters

When querying relations, authorization filters are resolved in order (first non-empty wins):

  1. Custom authorizer's authorizeRelation() method - if returns a filter, used exclusively
  2. Relation's auth option - if defined on the relation decorator
  3. Related DTO's @Authorize decorator - fallback to the related type's auth
note

Relation auth filters are NOT merged - the first non-empty result is used.

See Relation Filtering for details.