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

# Relations

> When using the  you can specify relations that should be exposed for the DTO using the following decorators.

* `@Relation` - A relation that is a single value (one-to-one, many-to-one)
* `@FilterableRelation` - A `@Relation` that enables filtering the parent by fields of the relation `DTO`.
* `@UnPagedRelation` - An array of relations (e.g, many-to-many, one-to-many) that returns all of the related records.
* `@FilterableUnPagedRelation` - An `@UnPagedRelation` that enables filtering the parent by fields of the relation `DTO`.
* `@OffsetConnection` - A connection that represents a collection (e.g, many-to-many, one-to-many) that uses `offset` based pagination.
* `@FilterableOffsetConnection` - An `@OffsetConnection` that enables filtering the parent by fields of the connection `DTO`.
* `@CursorConnection` - A connection that represents a collection (e.g, many-to-many, one-to-many) that uses `cursor` based pagination.
* `@FilterableCursorConnection` - A `@CursorConnection` that enables filtering the parent by fields of the connection `DTO`.

> [!WARNING]
>
> `@FilterableUnPagedRelation`, `@FilterableOffsetConnection`, and `@FilterableCursorConnection` are not supported by mongoose!

> [!NOTE]
>
> When loading relations a [dataloader](https://github.com/graphql/dataloader) that is scoped to the request will be used. This
> prevents the n+1 problem.

In the following examples we are going to use the following entities.

> [tab] TodoItemEntity
>
> ```ts todo-item/todo-item.entity.ts theme={null}
> import { Column, CreateDateColumn, Entity, PrimaryGeneratedColumn, UpdateDateColumn, OneToMany } from 'typeorm';
> import { SubTaskEntity } from '../sub-task/sub-task.entity';
>
> @Entity()
> export class TodoItemEntity {
>
>   @PrimaryGeneratedColumn()
>   id!: string;
>
>   @Column()
>   title!: string;
>
>   @Column()
>   completed!: boolean;
>
>   @OneToMany(
>     () => SubTaskEntity,
>     subTask => subTask.todoItem,
>   )
>   subTasks!: SubTaskEntity[];
>
>   @CreateDateColumn()
>   created!: Date;
>
>   @UpdateDateColumn()
>   updated!: Date;
> }
> ```

> [tab] SubTaskEntity
>
> ```ts sub-task/sub-task.entity.ts theme={null}
> import {
>
>   Entity,
>   PrimaryGeneratedColumn,
>   Column,
>   CreateDateColumn,
>   UpdateDateColumn,
>   ObjectType,
>   ManyToOne,
>   JoinColumn,
> } from 'typeorm';
> import { TodoItemEntity } from '../todo-item/todo-item.entity';
>
> @Entity()
> export class SubTaskEntity {
>
>   @PrimaryGeneratedColumn()
>   id!: string;
>
>   @Column()
>   title!: string;
>
>   @Column()
>   completed!: boolean;
>
>   @Column({ nullable: false })
>   todoItemId!: string;
>
>   @ManyToOne(
>     (): ObjectType<TodoItemEntity> => TodoItemEntity,
>     td => td.subTasks,
>     { onDelete: 'CASCADE', nullable: false },
>   )
>
>   @JoinColumn()
>   todoItem!: TodoItemEntity;
>
>   @CreateDateColumn()
>   created!: Date;
>
>   @UpdateDateColumn()
>   updated!: Date;
> }
> ```

## @Relation[​](#relation "Direct link to @Relation")

A relation that is a single value (one-to-one, many-to-one)

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

Based on the entities defined above we can add a `todoItem` relation to the `SubTask` by creating the following `SubTaskDTO` with a `@Relation` decorator.

```ts sub-task/sub-task.dto.ts theme={null}
import { FilterableField, IDField, Relation } from '@ptc-org/nestjs-query-graphql'
import { ObjectType, ID, GraphQLISODateTime } from '@nestjs/graphql'
import { TodoItemDTO } from '../todo-item/todo-item.dto.ts'

@ObjectType('SubTask')
@Relation('todoItem', () => TodoItemDTO, { update: { enabled: true } })
export class SubTaskDTO {

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

  @FilterableField()
  title!: string

  @FilterableField()
  completed!: boolean

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

  @FilterableField(() => GraphQLISODateTime)
  updated!: Date

  @FilterableField()
  todoItemId!: string
}
```

The `@Relation` decorator lets `nestjs-query` know to expose the following endpoints:

* `subTask.todoItem` - A `query` to retrieve the `SubTasks` `TodoItem`
* `setTodoItemOnSubTask` - A `mutation` to set the `TodoItem` on a `SubTask`.
* `removeTodoItemFromSubTask` - A `mutation` to remove a `TodoItem`/`SubTask` relation.
  * **NOTE** This does not typically remove either record just removes the relation.

To set up the resolver you can use the `NestjsQueryGraphQLModule`.

```ts sub-task/sub-task.module.ts theme={null}
import { NestjsQueryGraphQLModule } from '@ptc-org/nestjs-query-graphql'
import { NestjsQueryTypeOrmModule } from '@ptc-org/nestjs-query-typeorm'
import { Module } from '@nestjs/common'
import { SubTaskDTO } from './sub-task.dto'
import { SubTaskEntity } from './sub-task.entity'

@Module({
  imports: [
    NestjsQueryGraphQLModule.forFeature({
      imports: [NestjsQueryTypeOrmModule.forFeature([SubTaskEntity])],
      resolvers: [{ DTOClass: SubTaskDTO, EntityClass: SubTaskEntity }]
    })
  ]
})
export class SubTaskModule {}
```

`@ptc-org/nestjs-query-graphql` will then automatically create the following graphql definition:

```graphql theme={null}
type SubTask {
  id: ID!
  title: String!
  completed: Boolean!
  created: DateTime!
  updated: DateTime!
  todoItemId: String!
  todoItem: TodoItem!
}
```

The following mutations will also be automatically exposed.

```graphql theme={null}
type Mutation {
  setTodoItemOnSubTask(input: RelationInput!): SubTask!
}
input RelationInput {
  id: ID!
  relationId: ID!
}
```

> [!NOTE]
>
> If `remove.enabled` was set to `true` a `removeTodoItemFromSubTask` mutation would also be exposed with the same arguments as
> `setTodoItemOnSubTask`.

## @FilterableRelation[​](#filterablerelation "Direct link to @FilterableRelation")

The `@FilterableRelation` extends the `@Relation` decorator exposing the ability to filter the `DTO` that defines the relation by relation properties.

> [!WARNING]
>
> The `@FilterableRelation` decorator will **only** work with relations defined by the orm used (e.g. `typeorm`, `sequelize`). If
> your relations are federated or you are using `mongoose` you cannot use the `@FilterableRelation` decorator.

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

In this example we'll use the same Entities defined above to create a graphql endpoint that allows filtering `SubTasks` by `TodoItems`.

```ts sub-task/sub-task.dto.ts theme={null}
import { FilterableField, IDField, FilterableRelation } from '@ptc-org/nestjs-query-graphql'
import { ObjectType, ID, GraphQLISODateTime } from '@nestjs/graphql'
import { TodoItemDTO } from '../todo-item/todo-item.dto.ts'

@ObjectType('SubTask')
@FilterableRelation('todoItem', () => TodoItemDTO)
export class SubTaskDTO {

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

  @FilterableField()
  title!: string

  @FilterableField()
  completed!: boolean

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

  @FilterableField(() => GraphQLISODateTime)
  updated!: Date

  @FilterableField(() => ID)
  todoItemId!: string
}
```

Notice the use of `@FilterableRelation` instead of `@Relation`, by using the `@FilterableRelation` version `nestjs-query` will allow filtering on the `todoItem` relation.

The module definition remains the same.

```ts sub-task/sub-task.module.ts theme={null}
import { NestjsQueryGraphQLModule } from '@ptc-org/nestjs-query-graphql'
import { NestjsQueryTypeOrmModule } from '@ptc-org/nestjs-query-typeorm'
import { Module } from '@nestjs/common'
import { SubTaskDTO } from './sub-task.dto'
import { SubTaskEntity } from './sub-task.entity'

@Module({
  imports: [
    NestjsQueryGraphQLModule.forFeature({
      imports: [NestjsQueryTypeOrmModule.forFeature([SubTaskEntity])],
      resolvers: [{ DTOClass: SubTaskDTO, EntityClass: SubTaskEntity }]
    })
  ]
})
export class SubTaskModule {}
```

When querying for `SubTasks` you can now also filter on `todoItem` properties.

In this example we'll find all subTasks that are related to a `todoItem` with a title that starts with `Created`.

```graphql theme={null}
{
  subTasks(filter: { todoItem: { title: { like: "Create%" } } }) {
    title
    completed
  }
}
```

## @UnPagedRelation[​](#unpagedrelation "Direct link to @UnPagedRelation")

You can also use the `@UnPagedRelation` decorator to define a relation that does not use paging and returns an array of all the related records.

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

Based on the entity definition above we can define a `TodoItemDTO` with a `subTasks` relation.

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

@ObjectType('TodoItem')
@UnPagedRelation('subTasks', () => SubTaskDTO, { update: { enabled: true } })
export class TodoItemDTO {

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

  @FilterableField()
  title!: string

  @FilterableField()
  completed!: boolean

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

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

When specifying a many relation a couple of endpoints will automatically be generated. In this example the following are generated.

* `todoItem.subTasks` - A `query` endpoint to retrieve a `TodoItems` `SubTasks`.

  * The `subTasks` property will accept a [query](https://www.nestjs-query.dev/concepts/queries.md) to allow you to filter, and sort results.
  * The `subTasks` will be returned as an array of results.

* `addSubTasksToTodoItem` - A `mutation` to add `SubTasks` to a `TodoItem`.

To set up the resolver you can use the `NestjsQueryGraphQLModule`.

```ts todo-item/todo-item.module.ts theme={null}
import { NestjsQueryGraphQLModule } from '@ptc-org/nestjs-query-graphql'
import { NestjsQueryTypeOrmModule } from '@ptc-org/nestjs-query-typeorm'
import { Module } from '@nestjs/common'
import { TodoItemDTO } from './todo-item.dto'
import { TodoItemEntity } from './todo-item.entity'

@Module({
  imports: [
    NestjsQueryGraphQLModule.forFeature({
      imports: [NestjsQueryTypeOrmModule.forFeature([TodoItemEntity])],
      resolvers: [{ DTOClass: TodoItemDTO, EntityClass: TodoItemEntity }]
    })
  ]
})
export class TodoItemModule {}
```

The generated schema will contain a `TodoItem` type like the following.

```graphql theme={null}
type TodoItem {
  id: ID!
  title: String!
  completed: Boolean!
  created: DateTime!
  updated: DateTime!
  subTasks(filter: SubTaskFilter = {}, sorting: [SubTaskSort!] = []): [SubTask!]!
}
```

The following mutations will also be automatically exposed.

```graphql theme={null}
type Mutation {
  addSubTasksToTodoItem(input: RelationsInput!): TodoItem!
}
input RelationsInput {
  id: ID!
  relationIds: [ID!]!
}
```

> [!NOTE]
>
> If `remove.enabled` was set to `true` a `removeSubTasksFromTodoItem` mutation would also be exposed with the same arguments as
> `addSubTasksToTodoItem`.

## @FilterableUnPagedRelation[​](#filterableunpagedrelation "Direct link to @FilterableUnPagedRelation")

The `@FilterableUnPagedRelation` extends the `@UnPagedRelation` decorator exposing the ability to filter the `DTO` that defines the relation by relation properties.

> [!WARNING]
>
> The `@FilterableUnPagedRelation` decorator will **only** work with relations defined by the orm used (e.g. `typeorm`,
> `sequelize`). If your relations are federated or you are using `mongoose` you cannot use the `@FilterableUnPagedRelation`
> decorator.

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

In this example we'll use the same Entities defined above to create a graphql endpoint that allows filtering `TodoItems` by `SubTasks`.

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

@ObjectType('TodoItem')
@FilterableUnPagedRelation('subTasks', () => SubTaskDTO, { update: { enabled: true } })
export class TodoItemDTO {

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

  @FilterableField()
  title!: string

  @FilterableField()
  completed!: boolean

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

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

Notice the use of `@FilterableUnPagedRelation` instead of `@UnPagedRelation`, by using the `@FilterableUnPagedRelation` version `nestjs-query` will allow filtering on the `subTasks` relation.

The module definition remains the same.

```ts todo-item/todo-item.module.ts theme={null}
import { NestjsQueryGraphQLModule } from '@ptc-org/nestjs-query-graphql'
import { NestjsQueryTypeOrmModule } from '@ptc-org/nestjs-query-typeorm'
import { Module } from '@nestjs/common'
import { TodoItemDTO } from './todo-item.dto'
import { TodoItemEntity } from './todo-item.entity'

@Module({
  imports: [
    NestjsQueryGraphQLModule.forFeature({
      imports: [NestjsQueryTypeOrmModule.forFeature([TodoItemEntity])],
      resolvers: [{ DTOClass: TodoItemDTO, EntityClass: TodoItemEntity }]
    })
  ]
})
export class TodoItemModule {}
```

When querying for `TodoItems` you can now also filter on `subTasks` properties.

In this example we'll find all `todoItems` that are related to a `subTasks` that are completed.

```bash theme={null}
{
  todoItems(filter: { subTasks: { completed: { is: true } } }) {
    pageInfo {
      hasNextPage
      hasPreviousPage
      startCursor
      endCursor
    }
    edges {
      node {
        id
        title
        description
        completed
        subTasks {
          title
          description
          completed
        }
      }
      cursor
    }
  }
}
```

## @OffsetConnection[​](#offsetconnection "Direct link to @OffsetConnection")

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

Based on the entity definitions above we can create a `TodoItemDTO` with a connection to the `subTasks`.

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

@ObjectType('TodoItem')
@OffsetConnection('subTasks', () => SubTaskDTO, { update: { enabled: true } })
export class TodoItemDTO {

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

  @FilterableField()
  title!: string

  @FilterableField()
  completed!: boolean

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

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

When specifying a `@OffsetConnection` relation a couple of endpoints will automatically be generated. In this example the following are generated.

* `todoItem.subTasks` - A `query` to retrieve a `TodoItems` `SubTasks`.

  * The `subTasks` property will accept a [query](https://www.nestjs-query.dev/concepts/queries.md) to allow you to filter, page and sort results.
  * The `subTasks` property will return a offset based [connection](https://www.nestjs-query.dev/graphql/types.md#connectiontype) to page through results.

* `addSubTasksToTodoItem` - A `mutation` to add `SubTasks` to a `TodoItem`.

To set up the resolver you can use the `NestjsQueryGraphQLModule`.

```ts todo-item/todo-item.module.ts theme={null}
import { NestjsQueryGraphQLModule } from '@ptc-org/nestjs-query-graphql'
import { NestjsQueryTypeOrmModule } from '@ptc-org/nestjs-query-typeorm'
import { Module } from '@nestjs/common'
import { TodoItemDTO } from './todo-item.dto'
import { TodoItemEntity } from './todo-item.entity'

@Module({
  imports: [
    NestjsQueryGraphQLModule.forFeature({
      imports: [NestjsQueryTypeOrmModule.forFeature([TodoItemEntity])],
      resolvers: [{ DTOClass: TodoItemDTO, EntityClass: TodoItemEntity }]
    })
  ]
})
export class TodoItemModule {}
```

The generated schema will contain a `TodoItem` type like the following.

```graphql theme={null}
type TodoItem {
  id: ID!
  title: String!
  completed: Boolean!
  created: DateTime!
  updated: DateTime!
  subTasks(
    paging: OffsetPaging = { limit: 10 }
    filter: SubTaskFilter = {}
    sorting: [SubTaskSort!] = []
  ): TodoItemSubTasksConnection!
}
```

The following mutations will also be automatically exposed.

```graphql theme={null}
type Mutation {
  addSubTasksToTodoItem(input: RelationsInput!): TodoItem!
}
input RelationsInput {
  id: ID!
  relationIds: [ID!]!
}
```

> [!NOTE]
>
> If `remove.enabled` was set to `true` a `removeSubTasksFromTodoItem` mutation would also be exposed with the same arguments as
> `addSubTasksToTodoItem`.

### Total Count Example[​](#total-count-example "Direct link to Total Count Example")

> [!WARNING]
>
> Enabling `totalCount` can be expensive. If your table is large the `totalCount` query may be expensive, use with caution.

> [!NOTE]
>
> The `totalCount` field is not eagerly fetched. It will only be executed if the field is queried from the client.

When using the `@OffsetConnection` decorator you can enable the `totalCount` field. The `totalCount` field will return the total number of records included in the connection.

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

@ObjectType('TodoItem')
@OffsetConnection('subTasks', () => SubTaskDTO, { update: { enabled: true }, enableTotalCount: true })
export class TodoItemDTO {

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

  @FilterableField()
  title!: string

  @FilterableField()
  completed!: boolean

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

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

The generated graphql will include a `TodoItemSubTasksConnection` with a `totalCount` field.

```graphql theme={null}
type TodoItem {
  id: ID!
  title: String!
  completed: Boolean!
  created: DateTime!
  updated: DateTime!
  subTasks(
    paging: OffsetPaging = { limit: 10 }
    filter: SubTaskFilter = {}
    sorting: [SubTaskSort!] = []
  ): TodoItemSubTasksConnection!
}
type TodoItemSubTasksConnection {
  pageInfo: OffsetPageInfo!
  nodes: [SubTask!]!
  totalCount: Int!
}
```

## @FilterableOffsetConnection[​](#filterableoffsetconnection "Direct link to @FilterableOffsetConnection")

The `@FilterableOffsetConnection` extends the `@OffsetConnection` decorator exposing the ability to filter the `DTO` that defines the relation by relation properties.

> [!WARNING]
>
> The `@FilterableOffsetConnection` decorator will **only** work with relations defined by the orm used (e.g. `typeorm`,
> `sequelize`). If your relations are federated or you are using `mongoose` you cannot use the `@FilterableConnection` decorator.

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

In this example we'll use the same Entities defined above to create a graphql endpoint that allows filtering `TodoItems` by `subTasks`.

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

@ObjectType('TodoItem')
@QueryOptions({ pagingStrategy: PagingStrategies.OFFSET })
@FilterableOffsetConnection('subTasks', () => SubTaskDTO, { update: { enabled: true } })
export class TodoItemDTO {

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

  @FilterableField()
  title!: string

  @FilterableField()
  completed!: boolean

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

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

Notice the use of `@FilterableOffsetConnection` instead of `@OffsetConnection`, by using the `@FilterableOffsetConnection` version `nestjs-query` will allow filtering on the `subTasks` relation.

The module definition remains the same.

```ts todo-item/todo-item.module.ts theme={null}
import { PagingStrategies } from '@ptc-org/nestjs-query-core'
import { NestjsQueryGraphQLModule } from '@ptc-org/nestjs-query-graphql'
import { NestjsQueryTypeOrmModule } from '@ptc-org/nestjs-query-typeorm'
import { Module } from '@nestjs/common'
import { TodoItemDTO } from './todo-item.dto'
import { TodoItemEntity } from './todo-item.entity'

@Module({
  imports: [
    NestjsQueryGraphQLModule.forFeature({
      imports: [NestjsQueryTypeOrmModule.forFeature([TodoItemEntity])],
      resolvers: [{ DTOClass: TodoItemDTO, EntityClass: TodoItemEntity }]
    })
  ]
})
export class TodoItemModule {}
```

When querying for `TodoItems` you can now also filter on `subTasks` properties.

In this example we'll find all `todoItems` that have `subTasks` that are completed.

```graphql theme={null}
{
  todoItems(filter: { subTasks: { completed: { is: true } } }) {
    pageInfo {
      hasNextPage
      hasPreviousPage
    }
    nodes {
      id
      title
      description
      completed
      subTasks {
        nodes {
          title
          description
          completed
        }
      }
    }
  }
}
```

## @CursorConnection[​](#cursorconnection "Direct link to @CursorConnection")

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

Based on the entity definitions above we can create a `TodoItemDTO` with a connection to the `subTasks`.

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

@ObjectType('TodoItem')
@CursorConnection('subTasks', () => SubTaskDTO, { update: { enabled: true } })
export class TodoItemDTO {

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

  @FilterableField()
  title!: string

  @FilterableField()
  completed!: boolean

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

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

When specifying a `@CursorConnection` relation a couple of endpoints will automatically be generated. In this example the following are generated.

* `todoItem.subTasks` - A `query` to retrieve a `TodoItems` `SubTasks`.

  * The `subTasks` property will accept a [query](https://www.nestjs-query.dev/concepts/queries.md) to allow you to filter, page and sort results.
  * The `subTasks` property will return a cursor based [connection](https://www.nestjs-query.dev/graphql/types.md#connectiontype) to page through results.

* `addSubTasksToTodoItem` - A `mutation` to add `SubTasks` to a `TodoItem`.

To set up the resolver you can use the `NestjsQueryGraphQLModule`.

```ts todo-item/todo-item.module.ts theme={null}
import { NestjsQueryGraphQLModule } from '@ptc-org/nestjs-query-graphql'
import { NestjsQueryTypeOrmModule } from '@ptc-org/nestjs-query-typeorm'
import { Module } from '@nestjs/common'
import { TodoItemDTO } from './todo-item.dto'
import { TodoItemEntity } from './todo-item.entity'

@Module({
  imports: [
    NestjsQueryGraphQLModule.forFeature({
      imports: [NestjsQueryTypeOrmModule.forFeature([TodoItemEntity])],
      resolvers: [{ DTOClass: TodoItemDTO, EntityClass: TodoItemEntity }]
    })
  ]
})
export class TodoItemModule {}
```

The generated schema will contain a `TodoItem` type like the following.

```graphql theme={null}
type TodoItem {
  id: ID!
  title: String!
  completed: Boolean!
  created: DateTime!
  updated: DateTime!
  subTasks(
    paging: CursorPaging = { first: 10 }
    filter: SubTaskFilter = {}
    sorting: [SubTaskSort!] = []
  ): TodoItemSubTasksConnection!
}
```

The following mutations will also be automatically exposed.

```graphql theme={null}
type Mutation {
  addSubTasksToTodoItem(input: RelationsInput!): TodoItem!
}
input RelationsInput {
  id: ID!
  relationIds: [ID!]!
}
```

> [!NOTE]
>
> If `remove.enabled` was set to `true` a `removeSubTasksFromTodoItem` mutation would also be exposed with the same arguments as
> `addSubTasksToTodoItem`.

### Total Count Example[​](#total-count-example-1 "Direct link to Total Count Example")

> [!WARNING]
>
> Enabling `totalCount` can be expensive. If your table is large the `totalCount` query may be expensive, use with caution.

> [!NOTE]
>
> The `totalCount` field is not eagerly fetched. It will only be executed if the field is queried from the client.

When using the `@CursorConnection` decorator you can enable the `totalCount` field. The `totalCount` field will return the total number of records included in the connection.

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

@ObjectType('TodoItem')
@CursorConnection('subTasks', () => SubTaskDTO, { update: { enabled: true }, enableTotalCount: true })
export class TodoItemDTO {

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

  @FilterableField()
  title!: string

  @FilterableField()
  completed!: boolean

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

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

The generated graphql will include a `TodoItemSubTasksConnection` with a `totalCount` field.

```graphql theme={null}
type TodoItem {
  id: ID!
  title: String!
  completed: Boolean!
  created: DateTime!
  updated: DateTime!
  subTasks(
    paging: CursorPaging = { first: 10 }
    filter: SubTaskFilter = {}
    sorting: [SubTaskSort!] = []
  ): TodoItemSubTasksConnection!
}
type TodoItemSubTasksConnection {
  pageInfo: PageInfo!
  edges: [SubTaskEdge!]!
  totalCount: Int!
}
```

## @FilterableCursorConnection[​](#filterablecursorconnection "Direct link to @FilterableCursorConnection")

The `@FilterableCursorConnection` extends the `@CursorConnection` decorator exposing the ability to filter the `DTO` that defines the relation by relation properties.

> [!WARNING]
>
> The `@FilterableCursorConnection` decorator will **only** work with relations defined by the orm used (e.g. `typeorm`,
> `sequelize`). If your relations are federated or you are using `mongoose` you cannot use the `@FilterableConnection` decorator.

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

In this example we'll use the same Entities defined above to create a graphql endpoint that allows filtering `TodoItems` by `subTasks`.

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

@ObjectType('TodoItem')
@FilterableCursorConnection('subTasks', () => SubTaskDTO, { update: { enabled: true } })
export class TodoItemDTO {

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

  @FilterableField()
  title!: string

  @FilterableField()
  completed!: boolean

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

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

Notice the use of `@FilterableCursorConnection` instead of `@CursorConnection`, by using the `@FilterableCursorConnection` version `nestjs-query` will allow filtering on the `subTasks` relation.

The module definition remains the same.

```ts todo-item/todo-item.module.ts theme={null}
import { NestjsQueryGraphQLModule } from '@ptc-org/nestjs-query-graphql'
import { NestjsQueryTypeOrmModule } from '@ptc-org/nestjs-query-typeorm'
import { Module } from '@nestjs/common'
import { TodoItemDTO } from './todo-item.dto'
import { TodoItemEntity } from './todo-item.entity'

@Module({
  imports: [
    NestjsQueryGraphQLModule.forFeature({
      imports: [NestjsQueryTypeOrmModule.forFeature([TodoItemEntity])],
      resolvers: [{ DTOClass: TodoItemDTO, EntityClass: TodoItemEntity }]
    })
  ]
})
export class TodoItemModule {}
```

When querying for `TodoItems` you can now also filter on `subTasks` properties.

In this example we'll find all `todoItems` that have `subTasks` that are completed.

```bash theme={null}
{
  todoItems(filter: { subTasks: { completed: { is: true } } }) {
    pageInfo {
      hasNextPage
      hasPreviousPage
      startCursor
      endCursor
    }
    edges {
      node {
        id
        title
        description
        completed
        subTasks {
          edges {
            node {
              title
              description
              completed
            }
          }
        }
      }
      cursor
    }
  }
}
```

## Virtual Relations[​](#virtual-relations "Direct link to Virtual Relations")

You may run into a case where you have a `virtual` relation that does not exist in the database. `nestjs-query` supports this through the [RelationQueryService](https://www.nestjs-query.dev/concepts/services.md#relationqueryservice).

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

The following options can be passed to all relation/connection decorators, to customize functionality.

* `relationName` - The name of the relation to use when looking up the relation from the `QueryService`

* `nullable` - Set to `true` if the relation is nullable.

* `complexity` - Set to specify relation complexity. For more info see [complexity docs](https://docs.nestjs.com/graphql/complexity)

* `disableRead` - Set to `true` to disable read operations.

* `update`

  * `enabled` - Set to `true` to enable update operations.
  * `description` - The description of the update operation.
  * `complexity` - Set to specify relation complexity. For more info see [complexity docs](https://docs.nestjs.com/graphql/complexity)
  * `decorators=[]` - An array of custom `PropertyDecorator` or `MethodDecorators` to add to the endpoint.

* `remove`

  * `enabled` - Set to `true` to enable remove operations.
  * `description` - The description of the remove operation.
  * `complexity` - Set to specify relation complexity. For more info see [complexity docs](https://docs.nestjs.com/graphql/complexity)
  * `decorators=[]` - An array of custom `PropertyDecorator` or `MethodDecorators` to add to the endpoint.

* `allowFiltering` - Set to `true` to allow filtering on the relation.

* `guards=[]` - An array of [guards](https://docs.nestjs.com/guards) to add to `update` and `remove` endpoints.

* `interceptors=[]` - An array of [interceptors](https://docs.nestjs.com/interceptors) to add to `update` and `remove` endpoints.

* `pipes=[]` - An array of [pipes](https://docs.nestjs.com/pipes) to add to `update` and `remove` endpoints.

* `filters=[]` - An array of [filters](https://docs.nestjs.com/exception-filters) to add to `update` and `remove` endpoints.

> [!NOTE]
>
> `guards`, `pipes`, `interceptors` and `filters` will not work by default with relation endpoints. See
> [https://docs.nestjs.com/graphql/tooling#execute-enhancers-at-the-field-resolver-level](https://docs.nestjs.com/graphql/tooling#execute-enhancers-at-the-field-resolver-level)

### Custom Relation Name[​](#custom-relation-name "Direct link to Custom Relation Name")

Sometimes you may want to expose a relation that has a different name when persisted from the graphql property. To do this use the `relationName` property.

> [tab] Relation
>
> ```ts theme={null}
> // expose todoItem as todoItemRelation in graphql
>
> @Relation('todoItemRelation', () => TodoItemDTO, { relationName: 'todoItem' })
> ```

> [tab] CursorConnection
>
> ```ts theme={null}
> // expose subTasks as subTaskConnection in graphql
>
> @CursorConnection('subTaskConnection', () => SubTaskDTO, { relationName: 'subTasks' })
> ```

> [tab] OffsetConnection
>
> ```ts theme={null}
> // expose subTasks as subTaskConnection in graphql
>
> @OffsetConnection('subTaskConnection', () => SubTaskDTO, { relationName: 'subTasks' })
> ```

> [tab] UnPagedRelation
>
> ```ts theme={null}
> // expose subTasks as subTaskConnection in graphql
>
> @UnPagedRelation('subTasks', () => SubTaskDTO, { relationName: 'subTasks' })
> ```

### GraphQL lookahead[​](#graphql-lookahead "Direct link to GraphQL lookahead")

> [!WARNING]
>
> This functionality only works for typeorm!

When you want to optimze your database queries you can set `enableLookAhead`, this will join and select the relation when it's being fetched in the query.

> [tab] Relation
>
> ```ts theme={null}
> // enable enableLookAhead for the todoItem relation
>
> @Relation('todoItemRelation', () => TodoItemDTO, { enableLookAhead: true })
> ```

### Disable Reads[​](#disable-reads "Direct link to Disable Reads")

To disable the `read` `queries` you can set the `disableRead` option to `true`.

> [tab] Relation
>
> ```ts theme={null}
> // disable reading the todoItem relation
>
> @Relation('todoItem', () => TodoItemDTO, { disableRead: true })
> ```

> [tab] CursorConnection
>
> ```ts theme={null}
> // disable reading the connection
>
> @CursorConnection('subTasks', () => SubTaskDTO, { disableRead: true })
> ```

> [tab] OffsetConnection
>
> ```ts theme={null}
> // disable reading the relation
>
> @OffsetConnection('subTaskConnection', () => SubTaskDTO, { disableRead: true })
> ```

> [tab] UnPagedRelation
>
> ```ts theme={null}
> // disable reading the relation
>
> @UnPagedRelation('subTaskConnection', () => SubTaskDTO, { disableRead: true })
> ```

#### Disable `filter` or `sorting` in relations[​](#disable-filter-or-sorting-in-relations "Direct link to disable-filter-or-sorting-in-relations")

To disable the `filter` or `sorting` of relations you can set the `disableFilter` or/and `disableSort` option to `true`.

> [tab] Relation
>
> This is not available in `relation` as it will only fetch one record.

> [tab] CursorConnection
>
> ```ts theme={null}
> // disable reading the connection
>
> @CursorConnection('subTasks', () => SubTaskDTO, { disableFilter: true, disableSort: true })
> ```

> [tab] OffsetConnection
>
> ```ts theme={null}
> // disable reading the relation
>
> @OffsetConnection('subTaskConnection', () => SubTaskDTO, { disableFilter: true, disableSort: true })
> ```

> [tab] UnPagedRelation
>
> ```ts theme={null}
> // disable reading the relation
>
> @UnPagedRelation('subTaskConnection', () => SubTaskDTO, { disableFilter: true, disableSort: true })
> ```

### Enable Updates[​](#enable-updates "Direct link to Enable Updates")

To enable the `update` `mutations` you can set the `update.enabled` option to `true`.

> [tab] Relation
>
> ```ts theme={null}
> // disable updates to the relation
>
> @Relation('todoItem', () => TodoItemDTO, { update: { enabled: true } })
> ```

> [tab] CursorConnection
>
> ```ts theme={null}
> // disable updating subTasks
>
> @CursorConnection('subTasks', () => SubTaskDTO, { update: { enabled: true } })
> ```

> [tab] OffsetConnection
>
> ```ts theme={null}
> // disable updating subTasks
>
> @OffsetConnection('subTasks', () => SubTaskDTO, { update: { enabled: true } })
> ```

> [tab] UnPagedRelation
>
> ```ts theme={null}
> // disable updating subTasks
>
> @UnPagedRelation('subTasks', () => SubTaskDTO, { update: { enabled: true } })
> ```

### Enable Removes[​](#enable-removes "Direct link to Enable Removes")

To enable the `remove` `mutations` you can set the `remove.enabled` option to `true`.

> [tab] Relation
>
> ```ts theme={null}
> // disable removing the relation
>
> @Relation('todoItem', () => TodoItemDTO, { update: { enabled: true } })
> ```

> [tab] CursorConnection
>
> ```ts theme={null}
> // disable removing subTasks from the connection
>
> @CursorConnection('subTasks', () => SubTaskDTO, { update: { enabled: true } })
> ```

> [tab] OffsetConnection
>
> ```ts theme={null}
> // disable removing subTasks from the connection
>
> @OffsetConnection('subTasks', () => SubTaskDTO, { update: { enabled: true } })
> ```

> [tab] UnPagedRelation
>
> ```ts theme={null}
> // disable removing subTasks from the relations
>
> @UnPagedRelation('subTasks', () => SubTaskDTO, { update: { enabled: true } })
> ```

### Guards, Pipes and Filters[​](#guards-pipes-and-filters "Direct link to Guards, Pipes and Filters")

**NOTE** `guards`, `pipes`, `interceptors` and `filters` will not work by default with `read` endpoints. See [https://github.com/nestjs/graphql/issues/295](https://github.com/nestjs/graphql/issues/295)

In this example we'll just demonstrate using a `guard` but the same pattern applies for `pipes`, `filters` and `interceptors`

To set up a [guard](https://docs.nestjs.com/guards) for endpoint you can use the `guards` option.

Assume we have the following auth guard that checks for a certain header and value.

```ts auth.guard.ts theme={null}
import { CanActivate, ExecutionContext, Injectable, Logger } from '@nestjs/common'
import { Observable } from 'rxjs'
import { GqlExecutionContext } from '@nestjs/graphql'
import { AUTH_HEADER_NAME } from './constants'
import { config } from './config'

@Injectable()
export class AuthGuard implements CanActivate {

  private logger = new Logger(AuthGuard.name)
  canActivate(context: ExecutionContext): boolean | Promise<boolean> | Observable<boolean> {
    const ctx = GqlExecutionContext.create(context)
    const req = ctx.getContext().request
    this.logger.log(`Req = ${req.headers}`)
    return req.headers[AUTH_HEADER_NAME] === config.auth.header
  }
}
```

We can then add it to our relations

> [tab] Relation
>
> ```ts theme={null}
> // Add the AuthGuard using the guards option
>
> @Relation('todoItem', () => TodoItemDTO, { guards: [AuthGuard] })
> ```

> [tab] CursorConnection
>
> ```ts theme={null}
> // Add the AuthGuard using the guards option
>
> @CursorConnection('subTasks', () => SubTaskDTO, { guards: [AuthGuard] })
> ```

> [tab] OffsetConnection
>
> ```ts theme={null}
> // Add the AuthGuard using the guards option
>
> @OffsetConnection('subTasks', () => SubTaskDTO, { guards: [AuthGuard] })
> ```

> [tab] UnPagedRelation
>
> ```ts theme={null}
> // Add the AuthGuard using the guards option
>
> @UnPagedRelation('subTasks', () => SubTaskDTO, { guards: [AuthGuard] })
> ```

Now any requests that go to the `update` or `remove` endpoints will require the guard.

### Relation Mixin[​](#relation-mixin "Direct link to Relation Mixin")

If you are using the [resolvers individually](https://www.nestjs-query.dev/graphql/resolvers.md#individual-resolvers) you can use the following mixins to add relations functionality.

#### Relatable[​](#relatable "Direct link to Relatable")

When using The `Relatable` mixin adds all relations functionality to a resolver.

In this example we expose on read endpoints for todo items with the relations defined on the `TodoItemDTO`.

```ts todo-item/todo-item.resolver.ts theme={null}
import { ReadResolver, Relatable } from '@ptc-org/nestjs-query-graphql'
import { Resolver } from '@nestjs/graphql'
import { AuthGuard } from '../auth.guard'
import { SubTaskDTO } from '../sub-task/dto/sub-task.dto'
import { TodoItemDTO } from './todo-item.dto'
import { TodoItemService } from './todo-item.service'

const guards = [AuthGuard]

@Resolver(() => TodoItemDTO)
export class TodoItemResolver extends Relatable(TodoItemDTO)(ReadResolver(TodoItemDTO)) {

  constructor(readonly service: TodoItemService) {
    super(service)
  }
}
```


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.