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 '@nestjs-query/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, { disableRemove: 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 '@nestjs-query/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;}