Skip to content

Commit a62a9c3

Browse files
authored
docs(filtering): add "How Filters Are Applied" section (#424)
## Summary - Adds comprehensive documentation explaining how filters from different sources are combined - Clarifies that default filters are NOT merged (just a fallback when user provides no filter) - Documents that auth filters are always ANDed with user filters - Explains relation auth filter resolution order (first non-empty wins) - Includes filter flow diagram ## Test plan - [x] Run docs locally with `nx serve documentation` - [x] Verify new section renders correctly at `/docs/graphql/queries/filtering` - [x] Check internal links work (to authorization.mdx, dtos.mdx) 🤖 Generated with [Claude Code](https://claude.com/claude-code) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit * **Documentation** * Added comprehensive guide explaining how filters are applied, including filter sources, default behavior, authorization merging, and relation-filtering order. <sub>✏️ Tip: You can customize this high-level summary in your review settings.</sub> <!-- end of auto-generated comment: release notes by coderabbit.ai -->
2 parents ba27d31 + 1c68425 commit a62a9c3

File tree

1 file changed

+76
-0
lines changed

1 file changed

+76
-0
lines changed

documentation/docs/graphql/queries/filtering.mdx

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,3 +105,79 @@ You can find the documentation and an example in the [`QueryOptions` reference](
105105
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.
106106

107107
You can find the documentation and an example in the [`QueryOptions` reference](../dtos.mdx#allowed-boolean-expressions).
108+
109+
## How Filters Are Applied
110+
111+
Filters in `nestjs-query` come from multiple sources and combine differently depending on the source.
112+
113+
### Filter Sources
114+
115+
| Source | When Applied | How Combined |
116+
|--------|--------------|--------------|
117+
| User filter (GraphQL args) | Always | Base filter |
118+
| Default filter (`@QueryOptions`) | Only when user provides NO filter | Replaces empty filter |
119+
| Auth filter (`@Authorize`) | Always | ANDed with user filter |
120+
121+
### Default Filter Behavior
122+
123+
The `defaultFilter` from `@QueryOptions` is used as the GraphQL field's `defaultValue`. This means:
124+
125+
- ✅ If user provides NO filter → defaultFilter is used
126+
- ❌ If user provides ANY filter → defaultFilter is completely ignored
127+
128+
```ts
129+
@QueryOptions({ defaultFilter: { archived: { is: false } } })
130+
```
131+
132+
:::warning
133+
Default filter is NOT merged - it's a fallback. Use [authorization](../authorization.mdx) for filters that must always apply.
134+
:::
135+
136+
### Authorization Filter Behavior
137+
138+
Filters from `@Authorize` are **always merged** with the user's filter using AND logic:
139+
140+
```ts
141+
// User query
142+
filter: { title: { like: '%todo%' } }
143+
144+
// @Authorize returns
145+
{ ownerId: { eq: currentUserId } }
146+
147+
// Actual filter applied
148+
{ and: [{ title: { like: '%todo%' } }, { ownerId: { eq: currentUserId } }] }
149+
```
150+
151+
For more details, see [Authorization](../authorization.mdx).
152+
153+
### Filter Flow
154+
155+
```
156+
GraphQL Query (filter arg)
157+
158+
Default filter applied if user filter empty
159+
160+
Resolver receives query
161+
162+
Auth filter merged (AND)
163+
164+
QueryService.query()
165+
166+
ORM (TypeORM/Sequelize/Mongoose)
167+
168+
Database
169+
```
170+
171+
### Relation Filters
172+
173+
When querying relations, authorization filters are resolved in order (first non-empty wins):
174+
175+
1. **Custom authorizer's `authorizeRelation()` method** - if returns a filter, used exclusively
176+
2. **Relation's `auth` option** - if defined on the relation decorator
177+
3. **Related DTO's `@Authorize` decorator** - fallback to the related type's auth
178+
179+
:::note
180+
Relation auth filters are NOT merged - the first non-empty result is used.
181+
:::
182+
183+
See [Relation Filtering](../authorization.mdx#relation-filtering) for details.

0 commit comments

Comments
 (0)