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

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

> [!NOTE]
>
> There are multiple ways to set of references in `mongoose` there are intended as starting point.

> [!WARNING]
>
> Filtering on references is not supported by mongoose.

## One to Many/Many To One Example

To set up a one to many/many to one relationship in mongoose 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`

> [tab] Todo Item
>
> ```ts title="todo-item/todo-item.entity.ts" {32-36} theme={null}
> import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose'
> import { SchemaTypes, Types, Document } from 'mongoose'
>
> @Schema({ timestamps: true })
> export class TodoItemEntity extends Document {
>
>   @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()
>   createdBy?: string
>
>   @Prop()
>   updatedBy?: string
> }
>
> export const TodoItemEntitySchema = SchemaFactory.createForClass(TodoItemEntity)
> TodoItemEntitySchema.virtual('subTasks', {
>   ref: 'SubTaskEntity',
>   localField: '_id',
>   foreignField: 'todoItem'
> })
> ```

> [tab] Subtask
>
> ```ts title="sub-task/sub-task.entity.ts" {15-16} theme={null}
> import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose'
> import { SchemaTypes, Types, Document } from 'mongoose'
>
> @Schema({ timestamps: true })
> export class SubTaskEntity extends Document {
>
>   @Prop({ required: true })
>   title!: string
>
>   @Prop()
>   description?: string
>
>   @Prop({ required: true })
>   completed!: boolean
>
>   @Prop({ type: SchemaTypes.ObjectId, ref: 'TodoItemEntity', required: true })
>   todoItem!: Types.ObjectId
>
>   @Prop()
>   createdAt!: Date
>
>   @Prop()
>   updatedAt!: Date
>
>   @Prop()
>   createdBy?: string
>
>   @Prop()
>   updatedBy?: string
> }
>
> export const SubTaskEntitySchema = SchemaFactory.createForClass(SubTaskEntity)
> ```

Now that we have the relationship defined we can add the `@Relation` and `@CursorConnection` to our DTOs

> [tab] Todo Item
>
> ```ts title="todo-item/todo-item.dto.ts" theme={null}
> import { FilterableField, IDField, KeySet, CursorConnection } 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
>
> @CursorConnection('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] 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
> }
> ```

## Many To Many Example

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

> [tab] Todo Item
>
> ```ts title="todo-item/todo-item.entity.ts" {21-23} theme={null}
> import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose'
> import { SchemaTypes, Types, Document } from 'mongoose'
>
> @Schema({ timestamps: true })
> export class TodoItemEntity extends Document {
>
>   @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
>
>   // notice the brackets around the prop options
>
>   @Prop([{ type: SchemaTypes.ObjectId, ref: 'TagEntity' }])
>   tags!: Types.ObjectId[]
>
>   @Prop({ default: 0 })
>   priority!: number
>
>   @Prop()
>   createdBy?: string
>
>   @Prop()
>   updatedBy?: string
> }
>
> export const TodoItemEntitySchema = SchemaFactory.createForClass(TodoItemEntity)
> ```

> [tab] Tag
>
> ```ts title="tag/tag.entity.ts" {23-27} theme={null}
> import { Prop, Schema, SchemaFactory } from '@nestjs/mongoose'
> import { Document } from 'mongoose'
>
> @Schema({ timestamps: true })
> export class TagEntity extends Document {
>
>   @Prop({ required: true })
>   name!: string
>
>   @Prop()
>   createdAt!: Date
>
>   @Prop()
>   updatedAt!: Date
>
>   @Prop()
>   createdBy?: string
>
>   @Prop()
>   updatedBy?: string
> }
>
> export const TagEntitySchema = SchemaFactory.createForClass(TagEntity)
> TagEntitySchema.virtual('todoItems', {
>   ref: 'TodoItemEntity',
>   localField: '_id',
>   foreignField: 'tags'
> })
> ```

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

> [tab] Todo Item
>
> ```ts title="todo-item/todo-item.dto.ts" theme={null}
> import { FilterableField, IDField, KeySet, CursorConnection } 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'])
> @CursorConnection('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] Tag
>
> ```ts title="tag/tag.dto.ts" theme={null}
> import { FilterableField, IDField, KeySet, CursorConnection } 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
>
> @CursorConnection('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
> }
> ```


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