> ## Documentation Index
> Fetch the complete documentation index at: https://nestjs-query.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# DTOs

> The  package leverages most decorators from  and , with the exception of .

## `@FilterableField`[​](#filterablefield "Direct link to filterablefield")

The `FilterableField` is very similar to the [`Field`](https://typegraphql.ml/docs/types-and-fields.html) from TypeGraphQL, however it allows you to specify the fields that should be filterable when querying.

<Note>If you use the @nestjs/graphql `Field` decorator it will not be exposed in the query type for the DTO.</Note>

### Options[​](#options "Direct link to Options")

In addition to the normal field options you can also specify the following options

* `allowedComparisons` - An array of allowed comparisons. You can use this option to allow a subset of filter comparisons when querying through graphql.
  * This option is useful if the field is expensive to query on for certain operators, or your data source supports a limited set of comparisons.

* `filterRequired` - When set to `true` the field will be required whenever a `filter` is used. The `filter` requirement applies to all `read`, `update`, and `delete` endpoints that use a `filter`.

  * The `filterRequired` option is useful when your entity has an index that requires a subset of fields to be used to provide certain level of query performance.
  * **NOTE**: When a field is a required in a filter the default `filter` option is ignored.

* `filterOnly`- When set to `true`, the field will only appear as `filter` but isn't included as field inside the `ObjectType`.
  * This option is useful if you want to filter on foreign keys without resolving the relation but you don't want to have the foreign key show up as field in your query type for the DTO. This might be especially useful for [federated relations](/graphql/federation#reference-decorator)

### Example[​](#example "Direct link to Example")

In the following example we allow `id`, `title`, and `completed` to be used in queries.

todo-item.dto.ts

```ts theme={null}
import { FilterableField, IDField } from '@ptc-org/nestjs-query-graphql'
import { ObjectType, ID, GraphQLISODateTime, Field } from '@nestjs/graphql'

@ObjectType('TodoItem')
export class TodoItemDTO {

  @IDField(() => ID)
  id!: string

  @FilterableField()
  title!: string

  @FilterableField()
  completed!: boolean

  @Field(() => GraphQLISODateTime)
  created!: Date

  @Field(() => GraphQLISODateTime)
  updated!: Date
}
```

### Example - allowedComparisons[​](#example---allowedcomparisons "Direct link to Example - allowedComparisons")

In the following example the `allowedComparisons` option is demonstrated by restricting the comparisons that are allowed when filtering on certain fields.

For the `id` field only `eq`, `neq`, `in`, and `notIn` comparisons will be exposed in the schema.

The `title` field will only allow `eq`, `like`, and `notLike`.

todo-item.dto.ts

```ts theme={null}
import { FilterableField } from '@ptc-org/nestjs-query-graphql'
import { ObjectType, ID, GraphQLISODateTime, Field } from '@nestjs/graphql'

@ObjectType('TodoItem')
export class TodoItemDTO {

  @IDField(() => ID, { allowedComparisons: ['eq', 'neq', 'in', 'notIn'] })
  id!: string

  @FilterableField({ allowedComparisons: ['eq', 'like', 'notLike'] })
  title!: string

  @FilterableField()
  completed!: boolean

  @Field(() => GraphQLISODateTime)
  created!: Date

  @Field(() => GraphQLISODateTime)
  updated!: Date
}
```

### Example - filterRequired[​](#example---filterrequired "Direct link to Example - filterRequired")

In the following example the `filterRequired` option is applied to the `completed` field, ensuring that all endpoints that use a filter will require a comparison on the `completed` field.

todo-item.dto.ts

```ts theme={null}
import { FilterableField, IDField } from '@ptc-org/nestjs-query-graphql'
import { ObjectType, ID, GraphQLISODateTime, Field } from '@nestjs/graphql'

@ObjectType('TodoItem')
export class TodoItemDTO {

  @IDField(() => ID)
  id!: string

  @FilterableField()
  title!: string

  @FilterableField({ filterRequired: true })
  completed!: boolean

  @Field(() => GraphQLISODateTime)
  created!: Date

  @Field(() => GraphQLISODateTime)
  updated!: Date
}
```

### Example - filterOnly[​](#example---filteronly "Direct link to Example - filterOnly")

In the following example the `filterOnly` option is applied to the `assigneeId` field, which makes a query filterable by the id of an assigned user but won't return the `assigneeId` as field.

todo-item.dto.ts

```ts theme={null}
import { FilterableField, IDField } from '@ptc-org/nestjs-query-graphql'
import { ObjectType, ID, GraphQLISODateTime, Field } from '@nestjs/graphql'

@ObjectType('TodoItem')
@Relation('assignee', () => UserDTO)
export class TodoItemDTO {

  @IDField(() => ID)
  id!: string

  @FilterableField()
  title!: string

  @FilterableField()
  completed!: boolean

  @FilterableField({ filterOnly: true })
  assigneeId!: string

  @Field(() => GraphQLISODateTime)
  created!: Date

  @Field(() => GraphQLISODateTime)
  updated!: Date
}
```

## `@IDField`[​](#idfield "Direct link to idfield")

By default `nestjs-query` uses the default graphql `ID` scalar, if you need to use a different `graphql` `scalar` type you can use `@IDField` decorator. `nestjs-query` will use that `scalar` type passed to the `@IDField` for all auto-generated `query` and `mutation` endpoints that rely on an input for the `id` (e.g. `findById`, `updateOne`, `deleteOne`).

<Note>The `@IDField` uses the same options as `@FilterableField`.</Note>

<Info>
  You may have seen `@IDField` in various examples throughout the docs, this is because we recommend using `@IDField` by default.
  In the future if you need to change the type later on it should be a trivial change to find all fields that use the `@IDField`
  decorator to update.
</Info>

<Info>
  If you are using `query-typegoose`there is a known "won't fix" bug with `class-transformer`, where ObjectIds end up getting new values, instead of the hex value they should be. To remedy this, we have a special decorator called '@ObjectId\`. So, DTO's should use this as follow:

  ```ts theme={null}
  import { Field, GraphQLISODateTime, ID, ObjectType } from '@nestjs/graphql'
  import { CursorConnection, FilterableField, KeySet, ObjectId, QueryOptions } from '@ptc-org/nestjs-query-graphql'
  import mongoose from 'mongoose'
  import { AuthGuard } from '../../auth.guard'
  import { SubTaskDTO } from '../../sub-task/dto/sub-task.dto'
  import { TagDTO } from '../../tag/dto/tag.dto'

  @ObjectType('TodoItem')
  @KeySet(['id'])
  @QueryOptions({ enableTotalCount: true })
  @CursorConnection('subTasks', () => SubTaskDTO, { update: { enabled: true }, guards: [AuthGuard] })
  @CursorConnection('tags', () => TagDTO, { guards: [AuthGuard], update: { enabled: true }, remove: { enabled: true } })
  export class TodoItemDTO {

    @ObjectId()
    _id: mongoose.Types.ObjectId
  ```

  Notice the last two lines of code.
</Info>

### Example[​](#example-1 "Direct link to Example")

A common use case is to obscure an auto-incremented primary key.

In this example we'll do a simple version of that by declaring a new `ID` scalar that will `base64` encode all ids.

common/custom-id.scalar.ts

```ts theme={null}
import { Scalar, CustomScalar } from '@nestjs/graphql'
import { Kind, ValueNode } from 'graphql'

@Scalar('CustomID')
export class CustomIDScalar implements CustomScalar<string, number> {

  description = 'ID custom scalar type'
  private idPrefix = 'id:'
  parseValue(value: string): number {
    // parse a `base64` encoded id from the client when provided as a variable
    return parseInt(Buffer.from(value, 'base64').toString('utf8').replace(this.idPrefix, ''), 10)
  }
  serialize(value: number): string {
    // serialize a number into the base64 representation
    return Buffer.from(`${this.idPrefix}${value}`, 'utf8').toString('base64')
  }
  parseLiteral(ast: ValueNode): number | null {
    // parse a `base64` encoded id from the client when hardcoded into the query
    if (ast.kind === Kind.STRING) {
      return this.parseValue(ast.value)
    }
    return null
  }
}
```

Now lets register our `CustomID` scalar with `nestjs`.

common/common.module.ts

```ts theme={null}
import { Module } from '@nestjs/common'
import { CustomIDScalar } from './custom-id.scalar'

@Module({
  providers: [CustomIDScalar]
})
export class CommonModule {}
```

Once your `CustomIDScalar` is registered you can use it in your `DTOS`.

todo-item/dto/todo-item.dto.ts

```ts theme={null}
import { FilterableField, IDField } from '@ptc-org/nestjs-query-graphql'
import { ObjectType, GraphQLISODateTime } from '@nestjs/graphql'
import { CustomIDScalar } from '../../common/custom-id.scalar'

@ObjectType('TodoItem')
export class TodoItemDTO {

  @IDField(() => CustomIDScalar)
  id!: string

  @FilterableField()
  title!: string

  @FilterableField({ nullable: true })
  description?: string

  @FilterableField()
  completed!: boolean

  @FilterableField(() => GraphQLISODateTime, { filterOnly: true })
  created!: Date

  @FilterableField(() => GraphQLISODateTime, { filterOnly: true })
  updated!: Date
}
```

Now all `graphql` endpoints that need to use an `id` to query or mutate a `TodoItem` will use the `CustomIDScalar` type for the input.

### Example - Disable Filtering[​](#example---disable-filtering "Direct link to Example - Disable Filtering")

If you want to disable filtering and sorting on the `id` field you can use the `disableFilter` option.

todo-item/dto/todo-item.dto.ts

```ts theme={null}
import { FilterableField, IDField } from '@ptc-org/nestjs-query-graphql'
import { ObjectType, GraphQLISODateTime } from '@nestjs/graphql'
import { CustomIDScalar } from '../../common/custom-id.scalar'

@ObjectType('TodoItem')
export class TodoItemDTO {

  @IDField(() => CustomIDScalar, { disableFilter: true })
  id!: string

  @FilterableField()
  title!: string

  @FilterableField({ nullable: true })
  description?: string

  @FilterableField()
  completed!: boolean

  @FilterableField(() => GraphQLISODateTime, { filterOnly: true })
  created!: Date

  @FilterableField(() => GraphQLISODateTime, { filterOnly: true })
  updated!: Date
}
```

## `@QueryOptions`[​](#queryoptions "Direct link to queryoptions")

The `@QueryOptions` decorator can be used to override any defaults for querying functionality such as sorting, filtering, paging strategy, etc.

### Setting a default Filter[​](#setting-a-default-filter "Direct link to 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 option.

<Note>The default filter is only used when a filter is not provided in a query.</Note>

In this example we specify the default filter to be `completed IS TRUE`.

todo-item.dto.ts

```ts theme={null}
import { FilterableField, IDField, QueryOptions } from '@ptc-org/nestjs-query-graphql'
import { ObjectType, ID, GraphQLISODateTime, Field } from '@nestjs/graphql'

@ObjectType('TodoItem')
@QueryOptions({ defaultFilter: { completed: { is: true } } })
export class TodoItemDTO {

  @IDField(() => ID)
  id!: string

  @FilterableField()
  title!: string

  @FilterableField()
  completed!: boolean

  @Field(() => GraphQLISODateTime)
  created!: Date

  @Field(() => GraphQLISODateTime)
  updated!: Date
}
```

***

### Result Page Size[​](#result-page-size "Direct link to Result Page Size")

By default all results will be limited to 10 records.

To override the default you can override the default page size by setting the `defaultResultSize` option.

In this example we specify the `defaultResultSize` to 5 which means if a page size is not specified 5 results will be returned.

todo-item.dto.ts

```ts theme={null}
import { FilterableField, IDField, QueryOptions } from '@ptc-org/nestjs-query-graphql'
import { ObjectType, ID, GraphQLISODateTime, Field } from '@nestjs/graphql'

@ObjectType('TodoItem')
@QueryOptions({ defaultResultSize: 5 })
export class TodoItemDTO {

  @IDField(() => ID)
  id!: string

  @FilterableField()
  title!: string

  @FilterableField()
  completed!: boolean

  @Field(() => GraphQLISODateTime)
  created!: Date

  @Field(() => GraphQLISODateTime)
  updated!: Date
}
```

### Limiting Results Size[​](#limiting-results-size "Direct link to Limiting Results Size")

By default the max number records that can be returned is `50`.

To override the default you can override the following options specifying the `maxResultSize` option.

<Note>You can disable `maxResultSize` by setting the option to `-1`.</Note>

In this example we specify limit the max number of records an end user can request to 20.

todo-item.dto.ts

```ts theme={null}
import { FilterableField, IDField, QueryOptions } from '@ptc-org/nestjs-query-graphql'
import { ObjectType, ID, GraphQLISODateTime, Field } from '@nestjs/graphql'

@ObjectType('TodoItem')
@QueryOptions({ maxResultsSize: 20 })
export class TodoItemDTO {

  @IDField(() => ID)
  id!: string

  @FilterableField()
  title!: string

  @FilterableField()
  completed!: boolean

  @Field(() => GraphQLISODateTime)
  created!: Date

  @Field(() => GraphQLISODateTime)
  updated!: Date
}
```

***

### Paging Strategy[​](#paging-strategy "Direct link to Paging Strategy")

By default `nestjs-query` uses a `cursor` based paging strategy and returns a [connection](https://relay.dev/graphql/connections.htm) for all query many endpoints.

For a more in-depth overview of paging check out the [paging docs](/graphql/queries/paging)

You can override the default `pagingStrategy` to one of the following alternatives

* `OFFSET` - sets paging to allow `limit` and `offset` fields, and returns an `OffsetConnection`.
* `NONE` - turn off all paging and always return an `ArrayConnection`.

When using the `OFFSET` strategy your paging arguments for a many query will accept a `limit` and/or `offset`. This will also change the return type from a `CursorConnection` to an `OffsetConnection`.

todo-item.dto.ts

```ts theme={null}
import { FilterableField, IDField, QueryOptions, PagingStrategies } from '@ptc-org/nestjs-query-graphql'
import { ObjectType, ID, GraphQLISODateTime, Field } from '@nestjs/graphql'

@ObjectType('TodoItem')
@QueryOptions({ pagingStrategy: PagingStrategies.OFFSET })
export class TodoItemDTO {

  @IDField(() => ID)
  id!: string

  @FilterableField()
  title!: string

  @FilterableField()
  completed!: boolean

  @Field(() => GraphQLISODateTime)
  created!: Date

  @Field(() => GraphQLISODateTime)
  updated!: Date
}
```

To disable paging entirely you can use the `NONE` `pagingStrategy`. When using `NONE` an `ArrayConnection` will be returned.

todo-item.dto.ts

```ts theme={null}
import { FilterableField, IDField, QueryOptions, PagingStrategies } from '@ptc-org/nestjs-query-graphql'
import { ObjectType, ID, GraphQLISODateTime, Field } from '@nestjs/graphql'

@ObjectType('TodoItem')
@QueryOptions({ pagingStrategy: PagingStrategies.NONE })
export class TodoItemDTO {

  @IDField(() => ID)
  id!: string

  @FilterableField()
  title!: string

  @FilterableField()
  completed!: boolean

  @Field(() => GraphQLISODateTime)
  created!: Date

  @Field(() => GraphQLISODateTime)
  updated!: Date
}
```

### Paging with Total Count[​](#paging-with-total-count "Direct link to Paging with Total Count")

<Note>This section **ONLY** applies to `CURSOR` and `OFFSET` connections.</Note>

<Warning>
  Enabling `totalCount` can be expensive. If your table is large the `totalCount` query may be expensive, use with caution.
</Warning>

<Info>The `totalCount` field is not eagerly fetched. It will only be executed if the field is queried from the client.</Info>

When using the `CURSOR` (the default) or `OFFSET` paging strategy you have the option to expose a `totalCount` field to allow clients to fetch a total count of records in a connection.

To enable the `totalCount` field for connections set the `enableTotalCount` option to `true` using the `@QueryOptions` decorator.

todo-item.dto.ts

```ts theme={null}
import { FilterableField, IDField, QueryOptions, PagingStrategies } from '@ptc-org/nestjs-query-graphql'
import { ObjectType, ID, GraphQLISODateTime, Field } from '@nestjs/graphql'

@ObjectType('TodoItem')
@QueryOptions({ enableTotalCount: true })
export class TodoItemDTO {

  @IDField(() => ID)
  id!: string

  @FilterableField()
  title!: string

  @FilterableField()
  completed!: boolean

  @Field(() => GraphQLISODateTime)
  created!: Date

  @Field(() => GraphQLISODateTime)
  updated!: Date
}
```

When setting `enableTotalCount` to `true` you will be able to query for `totalCount` on `cursor` or offset connections

<Tabs>
  <Tab title="GraphQL">
    ```bash theme={null}
    {
      todoItems {
        totalCount
        pageInfo {
          hasNextPage
          hasPreviousPage
          startCursor
          endCursor
        }
        edges {
          node {
            id
            title
            description
          }
        }
      }
    }
    ```
  </Tab>

  <Tab title="Response">
    ```json theme={null}
    {
      "data": {
        "todoItems": {
          "totalCount": 5,
          "pageInfo": {
            "hasNextPage": false,
            "hasPreviousPage": false,
            "startCursor": "YXJyYXljb25uZWN0aW9uOjA=",
            "endCursor": "YXJyYXljb25uZWN0aW9uOjQ="
          },
          "edges": [
            {
              "node": {
                "id": "1",
                "title": "Create Nest App",
                "description": null
              }
            },
            {
              "node": {
                "id": "2",
                "title": "Create Entity",
                "description": null
              }
            },
            {
              "node": {
                "id": "3",
                "title": "Create Entity Service",
                "description": null
              }
            },
            {
              "node": {
                "id": "4",
                "title": "Add Todo Item Resolver",
                "description": null
              }
            },
            {
              "node": {
                "id": "5",
                "title": "How to create item With Sub Tasks",
                "description": null
              }
            }
          ]
        }
      }
    }
    ```
  </Tab>
</Tabs>

***

### Default Sort[​](#default-sort "Direct link to Default Sort")

When querying the default is based on the persistence layer. You can override the default by providing the `defaultSort` option.

In this example we specify the default sort to be by `title`.

todo-item.dto.ts

```ts theme={null}
import { FilterableField, IDField, QueryOptions, PagingStrategies } from '@ptc-org/nestjs-query-graphql'
import { SortDirection } from '@ptc-org/nestjs-query-core'
import { ObjectType, ID, GraphQLISODateTime, Field } from '@nestjs/graphql'

@ObjectType('TodoItem')
@QueryOptions({ defaultSort: [{ field: 'title', direction: SortDirection.ASC }] })
export class TodoItemDTO {

  @IDField(() => ID)
  id!: string

  @FilterableField()
  title!: string

  @FilterableField()
  completed!: boolean

  @Field(() => GraphQLISODateTime)
  created!: Date

  @Field(() => GraphQLISODateTime)
  updated!: Date
}
```

<Info>
  When we use the `@Relation` decorator or other [relation decorators](/graphql/relations) you might want to define the default sorting criteria like this:

  todo-item.dto.ts

  ```ts theme={null}
  import { SortDirection } from '@ptc-org/nestjs-query-core';

  // ...

  @Relation('assignee', () => UserDTO, {
    defaultSort: [{ field: 'id', direction: SortDirection.ASC }],
  })
  ```

  Note that default value for `defaultSort` is `[]`, meaning if you do **not** specify it you will receive the results as determined by your underlying database, which is unreliable and calculated based on how your database engine works.
</Info>

### Allowed Boolean Expressions[​](#allowed-boolean-expressions "Direct link to Allowed Boolean Expressions")

When filtering you can provide `and` and `or` expressions to provide advanced filtering. You can turn off either by using the `allowedBooleanExpressions` option.

In this example we will only allow `and` expressions.

todo-item.dto.ts

```ts theme={null}
import { FilterableField, IDField, QueryOptions, PagingStrategies } from '@ptc-org/nestjs-query-graphql'
import { ObjectType, ID, GraphQLISODateTime, Field } from '@nestjs/graphql'

@ObjectType('TodoItem')
@QueryOptions({ allowedBooleanExpressions: ['and'] })
export class TodoItemDTO {

  @IDField(() => ID)
  id!: string

  @FilterableField()
  title!: string

  @FilterableField()
  completed!: boolean

  @Field(() => GraphQLISODateTime)
  created!: Date

  @Field(() => GraphQLISODateTime)
  updated!: Date
}
```

To turn off all boolean expressions you can set `allowedBooleanExpressions` to an empty array. This is useful if you only allow filtering on certain fields and you want to disable all complex filtering.

In this example we will only allow `eq` comparisons on the id field and disable all `and`/`or` boolean expressions.

todo-item.dto.ts

```ts theme={null}
import { FilterableField, IDField, QueryOptions, PagingStrategies } from '@ptc-org/nestjs-query-graphql'
import { ObjectType, ID, GraphQLISODateTime, Field } from '@nestjs/graphql'

@ObjectType('TodoItem')
@QueryOptions({ allowedBooleanExpressions: ['and'] })
export class TodoItemDTO {

  @IDField(() => ID, { allowedComparisons: ['eq'] })
  id!: string

  @Field()
  title!: string

  @Field()
  completed!: boolean

  @Field(() => GraphQLISODateTime)
  created!: Date

  @Field(() => GraphQLISODateTime)
  updated!: Date
}
```

### Generated filter-type depth[​](#generated-filter-type-depth "Direct link to Generated filter-type depth")

When querying the default filter is one level deep. You can specify the generated filter-type depth by using the `filterDepth` option.

#### `n`-levels deep[​](#n-levels-deep "Direct link to n-levels-deep")

To generate a filter-type that is `n`-levels deep you can set the `filterDepth` option to `n`. Each level will be generated as a new input type with the name from the previous level as a prefix. In the following example it would generate `TodoItemFilter`, `TodoItemFilterSubTaskFilter` and `TodoItemFilterTagFilter`.

todo-item.dto.ts

```ts theme={null}
import { FilterableField, IDField, QueryOptions } from '@ptc-org/nestjs-query-graphql'
import { ObjectType, ID, GraphQLISODateTime, Field } from '@nestjs/graphql'
import { SubTaskDTO } from '../../sub-task/dto/sub-task.dto'
import { TagDTO } from '../../tag/dto/tag.dto'

@ObjectType('TodoItem')
// generate a filter-type that is 2 levels deep

@QueryOptions({ filterDepth: 2 })
@CursorConnection('subTasks', () => SubTaskDTO)
@CursorConnection('tags', () => TagDTO)
export class TodoItemDTO {

  @IDField(() => ID)
  id!: string

  @FilterableField()
  title!: string

  @FilterableField()
  completed!: boolean

  @Field(() => GraphQLISODateTime)
  created!: Date

  @Field(() => GraphQLISODateTime)
  updated!: Date
}
```

#### infinite depth[​](#infinite-depth "Direct link to infinite depth")

To generate a filter-type with infinite depth you can set the `filterDepth` option to `Number.POSITIVE_INFINITY`.

This will generate flat filter-types for each related entity. In the following example it would generate `TodoItemDeepFilter`, `SubTaskDeepFilter` and `TagDeepFilter`.

todo-item.dto.ts

```ts theme={null}
import { FilterableField, IDField, QueryOptions } from '@ptc-org/nestjs-query-graphql'
import { ObjectType, ID, GraphQLISODateTime, Field } from '@nestjs/graphql'
import { SubTaskDTO } from '../../sub-task/dto/sub-task.dto'
import { TagDTO } from '../../tag/dto/tag.dto'

@ObjectType('TodoItem')
// generate a filter-type with infinite depth

@QueryOptions({ filterDepth: Number.POSITIVE_INFINITY })
@CursorConnection('subTasks', () => SubTaskDTO)
@CursorConnection('tags', () => TagDTO)
export class TodoItemDTO {

  @IDField(() => ID)
  id!: string

  @FilterableField()
  title!: string

  @FilterableField()
  completed!: boolean

  @Field(() => GraphQLISODateTime)
  created!: Date

  @Field(() => GraphQLISODateTime)
  updated!: Date
}
```

[Edit this page](https://github.com/tripss/nestjs-query/edit/master/docs/graphql/dtos)
