【问题标题】:Best way to handle one-to-many with type-graphql typeorm and dataloader使用 type-graphql typeorm 和 dataloader 处理一对多的最佳方法
【发布时间】:2020-12-19 02:52:41
【问题描述】:

我正在尝试找出使用 type-graphql 和 typeorm 与 postgresql db 处理一对多关系的最佳方法(使用带有 express 的 apollo 服务器)。我有一个与课程表具有一对多关系的用户表。我目前处理此问题的方式是使用@RelationId 字段创建一列userCourseIds,然后使用@FieldResolver 和dataloader 批量获取属于该用户的课程。我的问题是使用@RelationId 字段,无论我是否实际查询userCourses,都会进行单独的查询来获取relationids。有没有办法在不进行额外查询的情况下处理这个问题,或者有更好的方法来处理一对多关系?

关系的用户方:

@OneToMany(() => Course, (course) => course.creator, { cascade: true })
userCourses: Course[];
@RelationId((user: User) => user.userCourses)
userCourseIds: string;

课程方面的关系:

@Field()
@Column()
creatorId: string;

@ManyToOne(() => User, (user) => user.userCourses)
creator: User;

userCourses 字段解析器:

@FieldResolver(() => [Course], { nullable: true })
async userCourses(@Root() user: User, @Ctx() { courseLoader }: MyContext) {
  const userCourses = await courseLoader.loadMany(user.userCourseIds);
  return userCourses;
}

【问题讨论】:

    标签: express graphql typeorm dataloader typegraphql


    【解决方案1】:

    userCourses 字段可以使用type-graphql-datalaoader 提供的@TypeormLoader 装饰器编写如下。

    @ObjectType()
    @Entity()
    class User {
      ...
    
      @Field((type) => [Course])
      @OneToMany(() => Course, (course) => course.creator, { cascade: true })
      @TypeormLoader((course: Course) => course.creatorId, { selfKey: true })
      userCourses: Course[];
    }
    
    @ObjectType()
    @Entity()
    class Course {
      ...
    
      @ManyToOne(() => User, (user) => user.userCourses)
      creator: User;
    
      @RelationId((course: Course) => course.creator)
      creatorId: string;
    }
    

    由于省略了userCourseIds,因此不再发出其他查询。虽然creatorId@RelationId 存在,但它不会发出额外的查询,因为实体有自己的值。

    更新:2021 年 6 月

    @TypeormLoader 不再需要参数。因此,如果愿意,@RelationId 可以完全省略。

    【讨论】:

    • @RelationId 为我进行额外查询。
    • 关系属性是否为实体所有? @ManyToOne@OneToOne@JoinColumn 拥有 ID。 @RelationId 他们不会触发额外的查询。
    • GraphQL 数据加载器如何与 @RelationId 一起工作?我认为它被忽略了。保证 N+1 期
    • 在上述情况下,creatorId 不会触发额外的查询,因为它是针对@ManyToOne 属性的。 @TypeormLoaderuserCourses 选择所有 courses,它们在后台的 batchLoadFn 中具有 user 的 id。
    • @TypeormLoader 需要 course.creatorId 以便知道选择查询的条件。
    猜你喜欢
    • 1970-01-01
    • 2019-10-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-02-10
    • 2018-06-20
    • 2011-02-18
    相关资源
    最近更新 更多