Skip to main content

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 .html)

note

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

warning

Filtering on references is not supported by Typegoose.

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.

todo-item/todo-item.entity.ts
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;
}

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

todo-item/todo-item.dto.ts
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;
}

Many To Many Example

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

todo-item/todo-item.entity.ts
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();
}
}

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

todo-item/todo-item.dto.ts
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;
}