使用 type-graphql typeorm 和 dataloader 处理一对多的最佳方法
Posted
技术标签:
【中文标题】使用 type-graphql typeorm 和 dataloader 处理一对多的最佳方法【英文标题】:Best way to handle one-to-many with type-graphql typeorm and 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;
【问题讨论】:
【参考方案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
属性的。 @TypeormLoader
的 userCourses
选择所有 course
s,它们在后台的 batchLoadFn 中具有 user
的 id。
@TypeormLoader
需要 course.creatorId
以便知道选择查询的条件。以上是关于使用 type-graphql typeorm 和 dataloader 处理一对多的最佳方法的主要内容,如果未能解决你的问题,请参考以下文章
对 Type-graphql 和 Typeorm 实体中的外键字段使用 ID 标量类型在语义上是不是正确?
如何将“typeorm”模型转换为 graphql 有效负载?