nestjs-rest-querynestjs-rest-query

Endpoint whitelist rules

Complete reference for supported query parameters — filters, operators, sorts, fields, includes, and pagination.

Filters and operators

Format: filter[field][operator]=value

The field must be listed in the endpoint RulesConfig.filters — unauthorized fields throw 400 Bad Request.

Available operators

OperatorDescription
eqEqual
neNot equal
gtGreater than
gteGreater than or equal
ltLess than
lteLess than or equal
likeContains (case-sensitive, automatic wildcards)
ilikeContains (case-insensitive, portable across DBs)
notLikeDoes not contain (case-sensitive)
notIlikeDoes not contain (case-insensitive)
inIn a list (CSV)
notInNot in a list (CSV)
betweenBetween two values (val1,val2)
isNullNull (true) or not null (false)

Operators with special behavior

in and notIn — the value is a CSV list. Each item is treated as a separate element:

filter[status][in]=active,pending
filter[status][notIn]=deleted,banned

between — two comma-separated values, applied as BETWEEN val1 AND val2:

filter[createdAt][between]=2024-01-01,2024-12-31
filter[price][between]=10,99

isNulltrue generates IS NULL, false generates IS NOT NULL. There is no separate isNotNull operator:

filter[deletedAt][isNull]=true
filter[photoUrl][isNull]=false

ilike — uses LOWER() to ensure portability across PostgreSQL, MySQL, and SQLite. For PostgreSQL with large volumes, consider creating a functional index on LOWER(field) for better performance:

filter[name][ilike]=joao

Restricting operators globally

By default all operators are allowed. To restrict them, configure operators.allowed in forRoot:

DynamicQueryBuilderModule.forRoot({
  operators: {
    allowed: ['eq', 'ne', 'like', 'in'],
  },
});

Operators outside the list throw BadRequestException.

Restricting operators per endpoint

If a route defines operators inside its RulesConfig, that endpoint-specific whitelist overrides the global forRoot setting for that route.

const rules: RulesConfig = {
  filters: ['name', 'status'],
  operators: {
    allowed: ['eq', 'like'],
  },
};

Use this when one endpoint needs a tighter whitelist than the rest of the app. An empty endpoint object, operators: {}, means "allow all operators" for that route even if the global config is restricted.


Sorts

Format: sort=field,-other (- prefix for desc, no prefix for asc)

The field must be listed in RulesConfig.sorts.

Warning: when fields is defined in RulesConfig, sort fields must also be present in fields. If a field is in sorts but missing from fields, TypeORM throws an error because the field was not selected in the query. Keep sorts and fields in sync, or omit fields if you do not need to restrict column selection.


Fields

Format: fields=id,name,email

Restricts the columns returned by the query (SELECT). When omitted, all entity columns are returned.

The field must be listed in RulesConfig.fields; the response is constrained to the declared field whitelist.

Defining fields in RulesConfig also affects sorts — see the warning above.


Includes

Format: includes=company,roles

Loads relations through the configured adapter. Each relation must be listed in RulesConfig.includes — unauthorized relations throw 400 Bad Request.

There is no implicit eager load: includes are only applied when the includes parameter is present in the query string.


Pagination

ParameterTypeDefaultDescription
pagenumber1Current page
perPagenumber10Items per page (maximum: 100)
paginatetrue / falsetruefalse disables pagination and returns all records

The defaults and maximum perPage are configurable through forRoot:

DynamicQueryBuilderModule.forRoot({
  pagination: {
    defaultPerPage: 20,
    maxPerPage: 200,
  },
});

Response with active pagination

{
  "data": [...],
  "page": 1,
  "perPage": 10,
  "total": 42,
  "lastPage": 5
}

Response with paginate=false

{
  "data": [...]
}
Edit this page on GitHub

On this page