> ## 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.

# Relations

Relations work a little differently in `typegoose` when compared to other relational ORMs such as `sequelize` or
`typeorm`. You can read more about relations (references) in `typegoose` \[here]\([https://mongoosejs.com/docs/populate](https://mongoosejs.com/docs/populate)
.html)

<Note>There are multiple ways to set of references in Typegoose. These are intended as a starting point.</Note>

<Warning>Filtering on references is not supported by Typegoose.</Warning>

## One to Many/Many To One Example

To set up a one to many/many to one relationship in Typegoose, you will store a reference in your document.

For example, lets add sub tasks to our todo items by storing a `todoItem` ref on our `subTask` and an array of sub-tasks on our `todoItem` entity.

<Tabs>
  <Tab title="Todo Item">
    ```ts title="todo-item/todo-item.entity.ts" {24-25} theme={null}
    import { Prop, modelOptions } from '@typegoose/typegoose'
    import { Base } from '@typegoose/typegoose/lib/defaultClasses'

    @modelOptions({ schemaOptions: { timestamps: true } })
    export class TodoItemEntity extends Base {

      @Prop({ required: true })
      title!: string

      @Prop()
      description?: string

      @Prop({ required: true })
      completed!: boolean

      @Prop({ default: Date.now })
      createdAt!: Date

      @Prop({ default: Date.now })
      updatedAt!: Date

      @Prop({ default: 0 })
      priority!: number

      @Prop({ ref: () => SubTaskEntity })
      subTasks: Ref<SubTaskEntity>[]

      @Prop()
      createdBy?: string

      @Prop()
      updatedBy?: string
    }
    ```
  </Tab>

  <Tab title="Subtask">
    ```ts title="sub-task/sub-task.entity.ts" {15-16} theme={null}
    import { Prop, modelOptions, Ref } from '@typegoose/typegoose'
    import { Base } from '@typegoose/typegoose/lib/defaultClasses'

    @modelOptions({ schemaOptions: { timestamps: true } })
    export class SubTaskEntity extends Base {

      @Prop({ required: true })
      title!: string

      @Prop()
      description?: string

      @Prop({ required: true })
      completed!: boolean

      @Prop({ ref: () => TodoItemEntity, required: true })
      todoItem!: Ref<TodoItemEntity>

      @Prop()
      createdAt!: Date

      @Prop()
      updatedAt!: Date

      @Prop()
      createdBy?: string

      @Prop()
      updatedBy?: string
    }
    ```
  </Tab>
</Tabs>

Now that we have the relationships defined, we can add the `@Relation` and `@Connection` to our DTOs

<Tabs>
  <Tab title="Todo Item">
    ```ts title="todo-item/todo-item.dto.ts" theme={null}
    import { FilterableField, IDField, KeySet, Connection } from '@ptc-org/nestjs-query-graphql'
    import { ObjectType, ID, GraphQLISODateTime, Field } from '@nestjs/graphql'
    import { SubTaskDTO } from '../../sub-task/dto/sub-task.dto'

    @ObjectType('TodoItem')
    @KeySet(['id'])
    // disable the remove because mongoose does not support removing a virtual

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

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

      @FilterableField()
      title!: string

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

      @FilterableField()
      completed!: boolean

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

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

      @Field()
      age!: number

      @FilterableField()
      priority!: number

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

      @FilterableField({ nullable: true })
      updatedBy?: string
    }
    ```
  </Tab>

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

    @ObjectType('SubTask')
    @KeySet(['id'])
    // disable the remove because a sub task cannot exist without a todoitem

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

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

      @FilterableField()
      title!: string

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

      @FilterableField()
      completed!: boolean

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

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

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

      @FilterableField({ nullable: true })
      updatedBy?: string
    }
    ```
  </Tab>
</Tabs>

## Many To Many Example

In this example, we'll add `tags` to `todoItems` by storing an array of `tag` references on the `todoItems`.

<Tabs>
  <Tab title="Todo Item">
    ```ts title="todo-item/todo-item.entity.ts" {21-23} theme={null}
    import { Prop, modelOption, Ref } from '@typegoose/typegoose'
    import { Base } from '@typegoose/typegoose/lib/defaultClasses'

    @modelOptions({ schemaOptions: { timestamps: true } })
    export class TodoItemEntity extends Base {

      @Prop({ required: true })
      title!: string

      @Prop()
      description?: string

      @Prop({ required: true })
      completed!: boolean

      @Prop({ default: Date.now })
      createdAt!: Date

      @Prop({ default: Date.now })
      updatedAt!: Date

      @Prop({ ref: () => TagEntity })
      tags!: Ref<TagEntity>[]

      @Prop({ default: 0 })
      priority!: number

      @Prop()
      createdBy?: string

      @Prop()
      updatedBy?: string

      public get id(): string {
        // eslint-disable-next-line no-underscore-dangle
        return this._id.toHexString()
      }
    }
    ```
  </Tab>

  <Tab title="Tag">
    ```ts title="tag/tag.entity.ts" {33-38} theme={null}
    import { Base } from '@typegoose/typegoose/lib/defaultClasses'
    import { Prop, modelOptions, Ref } from '@typegoose/typegoose'
    import { Types } from 'mongoose'
    import { TodoItemEntity } from '../todo-item/todo-item.entity'

    @modelOptions({
      schemaOptions: {
        timestamps: true,
        collection: 'tags',
        toObject: { virtuals: true }
      }
    })
    export class TagEntity implements Base {

      _id!: Types.ObjectId

      id!: string

      @Prop({ required: true })
      name!: string

      @Prop()
      createdAt!: Date

      @Prop()
      updatedAt!: Date

      @Prop()
      createdBy?: string

      @Prop()
      updatedBy?: string

      @Prop({
        ref: 'TodoItemEntity',
        localField: '_id',
        foreignField: 'tags'
      })
      todoItems?: Ref<TodoItemEntity>[]
    }
    ```
  </Tab>
</Tabs>

Now that we have the relationship defined, we can add the `@Connection` to our DTOS

<Tabs>
  <Tab title="Todo Item">
    ```ts title="todo-item/todo-item.dto.ts" theme={null}
    import { FilterableField, IDField, KeySet, Connection } from '@ptc-org/nestjs-query-graphql'
    import { ObjectType, ID, GraphQLISODateTime, Field } from '@nestjs/graphql'
    import { TagDTO } from '../../tag/dto/tag.dto'

    @ObjectType('TodoItem')
    @KeySet(['id'])
    @Connection('tags', () => TagDTO)
    export class TodoItemDTO {

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

      @FilterableField()
      title!: string

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

      @FilterableField()
      completed!: boolean

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

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

      @Field()
      age!: number

      @FilterableField()
      priority!: number

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

      @FilterableField({ nullable: true })
      updatedBy?: string
    }
    ```
  </Tab>

  <Tab title="Tag">
    ```ts title="tag/tag.dto.ts" theme={null}
    import { FilterableField, IDField, KeySet, Connection } from '@ptc-org/nestjs-query-graphql'
    import { ObjectType, ID, GraphQLISODateTime } from '@nestjs/graphql'
    import { TodoItemDTO } from '../../todo-item/dto/todo-item.dto'

    @ObjectType('Tag')
    @KeySet(['id'])
    // disable update and remove since it is a virtual in the entity

    @Connection('todoItems', () => TodoItemDTO)
    export class TagDTO {

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

      @FilterableField()
      name!: string

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

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

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

      @FilterableField({ nullable: true })
      updatedBy?: string
    }
    ```
  </Tab>
</Tabs>

## Discriminators

Typegoose supports mongoose [discriminators](https://mongoosejs.com/docs/discriminators.html). `nestjs-query` provides support for them through the `NestjsQueryTypegooseModule`.

To use discriminators you need to define them in your `NestjsQueryTypegooseModule.forFeature` call.

When working with discriminators, `nestjs-query` requires you to provide a service class for each discriminated entity. This is necessary for the auto-generated resolvers to be created correctly. These service classes are also the perfect place to add any custom business logic for your discriminated entities.

```ts title="todo-item/todo-item.module.ts" theme={null}
import { NestjsQueryGraphQLModule } from '@ptc-org/nestjs-query-graphql'
import { NestjsQueryTypegooseModule, TypegooseQueryService } from '@ptc-org/nestjs-query-typegoose'
import { Module } from '@nestjs/common'
import { TodoItemEntity } from './entities/todo-item.entity'
import { TodoTaskEntity } from './entities/todo-task.entity'
import { TodoAppointmentEntity } from './entities/todo-appointment.entity'
import { TodoItemDTO } from './dto/todo-item.dto'
import { TodoTaskDTO } from './dto/todo-task.dto'
import { TodoAppointmentDTO } from './dto/todo-appointment.dto'
import { CreateTodoTaskInput } from './dto/create-todo-task.input'
import { CreateTodoAppointmentInput } from './dto/create-todo-appointment.input'
import { InjectModel } from '@m8a/nestjs-typegoose'
import { ReturnModelType } from '@typegoose/typegoose'

const typegooseModule = NestjsQueryTypegooseModule.forFeature([
  {
    typegooseClass: TodoItemEntity,
    discriminators: [{ typegooseClass: TodoTaskEntity }, { typegooseClass: TodoAppointmentEntity }]
  }
])

class TodoTaskEntityService extends TypegooseQueryService<TodoTaskEntity> {

  constructor(@InjectModel(TodoTaskEntity) readonly model: ReturnModelType<typeof TodoTaskEntity>) {
    super(model)
  }
}

class TodoAppointmentService extends TypegooseQueryService<TodoAppointmentEntity> {

  constructor(@InjectModel(TodoAppointmentEntity) readonly model: ReturnModelType<typeof TodoAppointmentEntity>) {
    super(model)
  }
}

@Module({
  imports: [
    NestjsQueryGraphQLModule.forFeature({
      imports: [typegooseModule],
      resolvers: [
        {
          DTOClass: TodoItemDTO,
          EntityClass: TodoItemEntity,
          create: { disabled: true }, // Disable create for the base entity
          update: { disabled: true } // Disable update for the base entity
        },
        {
          DTOClass: TodoTaskDTO,
          EntityClass: TodoTaskEntity,
          // Tell the resolver to use our custom input for the create operation
          CreateDTOClass: CreateTodoTaskInput,
          ServiceClass: TodoTaskEntityService
        },
        {
          DTOClass: TodoAppointmentDTO,
          EntityClass: TodoAppointmentEntity,
          // Tell the resolver to use our custom input for the create operation
          CreateDTOClass: CreateTodoAppointmentInput,
          ServiceClass: TodoAppointmentService
        }
      ],
      services: [TodoTaskEntityService, TodoAppointmentService]
    })
  ]
})
export class TodoItemModule {}
```
