Search code examples
nestjstypeorm

TypeORM: Joining when we have one to many and many to one relationship


@Entity()
export class User {
  @PrimaryColumn()
  id: string;

  @Column({unique: true})
  username: string;

  @Column({unique: true})
  email: string;

  @OneToMany(type => Post, post => post.id)
  posts: Post[];
}

@Entity()
export class Post {

  @PrimaryGeneratedColumn()
  id: number;

  @ManyToOne(type => User, user => user.posts)
  @JoinColumn({name: 'user_id'})
  user: User;

  @OneToMany(type => Image, image => image.id)
  images: Image[];
}
 
@Entity()
export class Image {
  @PrimaryGeneratedColumn()
  id: number;

  @ManyToOne(type => Post, post => post.images)
  @JoinColumn({name : 'post_id'})
  post: Post;
}

I have these 3 entities and I want to make a query to have all the posts from a user and for that post to get all the images. I am trying to do this using the following code:

return await this.postRepository.createQueryBuilder("post")
  .innerJoinAndSelect("post.images", "image")
  .where("user_id = :userId", {userId: id})
  .getMany();

And I get the following error:

Cannot read property 'joinColumns' of undefined

I also tried this instead of the .innerJoin from above:

.innerJoinAndSelect(Image, "image", "image.post_id = post.id")

This way I don't get that error anymore, but as a result I get only the post and I don't get the images from it


Solution

  • I have been struggling with the same problem myself.

    You should change the relation here:

    @OneToMany(type => Image, image => image.id)
    images: Image[];
    

    To this:

    @OneToMany(type => Image, image => image.post)
    images: Image[];
    

    Notice that image.id should be image.post instead to match the inverse side.

    *Edit => Over here the same problem appears:

    @OneToMany(type => Post, post => post.id)
    posts: Post[];
    

    This relation should also have the inverse side, post.id should be post.user instead:

    @OneToMany(type => Post, post => post.user)
    posts: Post[];
    

    Be careful about this since it doesn't throw any errors until runtime.

    I just tested this query with the above modifications and the error is gone:

    return await this.postRepository.find({
      relations: ['images', 'user'],
      where: { user: { id: id } },
    });
    

    You may also omit the @JoinColumn() decorators, as they are not necessary in one to many and many to one relationships, you can see it mentioned in the official docs:

    You can omit @JoinColumn in a @ManyToOne / @OneToMany relation. @OneToMany cannot exist without @ManyToOne. If you want to use @OneToMany, @ManyToOne is required. Where you set @ManyToOne - its related entity will have "relation id" and foreign key.

    Refer to the TypeORM documentation for more details about this, you will also find an example of this type of relation.