Search code examples
mysqltypescriptnestjstypeorm

Complex relations TypeORM / MySQL


I'm using TypeORM with MySQL, I have two Entity, User and Project:

@Entity()
class User {
    @PrimaryGeneratedColumn('uuid') 
    id: string;  

    @Column({})
    name: string;
}

@Entity()
class Project {
    @PrimaryGeneratedColumn('uuid') 
    id: string;  

    @Column({})
    name: string;
}

I would like to add a third entity, Invitation. An invitation is composed of the userId and the projectId as the key. A user can be invited to multiple projects but only once for each project. I also want to store the user who sends the invitation.

@Entity()
class Invitation {
    @PrimaryGeneratedColumn('uuid') 
    id: string;  

    @Column({})
    userID: string;

    @Column({})
    invitedById: string;

    @Column({})
    projectID: string;

    @Column({})
    otherInformations: string;

}

How can I achieve this using TypeORM Relations decorators?

Thanks, any help is appreciated, I'm still quite new to the ORM world.

Have a nice end of weekend.


Solution

  • This is what it looks like in the end:

    @Entity()
    class Invitation {
      @PrimaryGeneratedColumn("uuid")
      id: string;
    
      @Column({})
      projectID: string;
    
      @Column({})
      otherInformations: string;
    
      // Relations
      @ManyToOne(() => User, (user) => user.invitations)
      user: User;
    
      @ManyToOne(() => Project, (project) => project.invitations)
      project: Project;
    
      @ManyToOne(() => User, (user) => user.invited)
      invitedById: User;
    }
    
    @Entity()
    class Project {
      @PrimaryGeneratedColumn("uuid")
      id: string;
    
      @Column({})
      name: string;
    
      @OneToMany(() => Invitation, (invitation) => invitation.project)
      invitations: Invitation[];
    }
    
    @Entity()
    class User {
      @PrimaryGeneratedColumn("uuid")
      id: string;
    
      @Column({})
      name: string;
    
      @OneToMany(() => Invitation, (invitation) => invitation.user)
      invitations: Invitation[];
    
      @OneToMany(() => Invitation, (invitation) => invitation.invitedById)
      invited: Invitation[];
    }
    

    I'm trying to explain it but for a clearer explanation about relations, you can watch this video: https://www.youtube.com/watch?v=8kZ7W-bI5qQ&t=239s&ab_channel=BenAwad (just ignore the graphql part) or read the documentation about relations here: https://typeorm.io/#/relations

    So your Invitation entity is the connection between the User and the Project as a many-to-many relation. You access the user via the @ManyToOne() decorator which creates a relation between many users and one invitation. The same with your Project entity:

      // Invitation.ts
      @ManyToOne(() => User, (user) => user.invitations)
      user: User;
    
      @ManyToOne(() => Project, (project) => project.invitations)
      project: Project;
    

    In each Entity, you add the opposite relation to the Invitation entity

      // User.ts
      @OneToMany(() => Invitation, (invitation) => invitation.user)
      invitations: Invitation[];
    
      @OneToMany(() => Invitation, (invitation) => invitation.invitedById)
      invited: Invitation[];
    
      // Project.ts
      @OneToMany(() => Invitation, (invitation) => invitation.project)
      invitations: Invitation[];
    

    Notice we use [] here because it's a ...ToMany() relation

    invitedById is added the same way:

      // Invitation.ts
      @ManyToOne(() => User, (user) => user.invited)
      invitedById: User;
    
      // User.ts
      @OneToMany(() => Invitation, (invitation) => invitation.invitedById)
      invited: Invitation[];