使用graphql类型处理子筛选器上的关系数据的最佳方法
我对graphql/typeorm之间的关系数据查询有疑问。 最好的解释方法是举个例子:) 为了回答我的问题,我使用了prisma API,例如() 此API是StarWars GraphQL API的一个示例 如果我想获得所有电影和相关角色,我会这样查询: 案例A 在这种情况下,可以一次性调用关系数据库,同时检索电影和角色(sql select with join) 我的问题是,在这样的查询中添加过滤器时,如何保持sql性能 案例B 在本例中,我们似乎必须使用FieldResolver执行此操作,并执行其他数据库调用以检索子级 要澄清,请参见以下示例: 案例A(简单实施) 对于typescript和typeorm中的nodejs后端,我们可以这样做: 实体: 解析程序:使用graphql类型处理子筛选器上的关系数据的最佳方法,graphql,typeorm,typegraphql,Graphql,Typeorm,Typegraphql,我对graphql/typeorm之间的关系数据查询有疑问。 最好的解释方法是举个例子:) 为了回答我的问题,我使用了prisma API,例如() 此API是StarWars GraphQL API的一个示例 如果我想获得所有电影和相关角色,我会这样查询: 案例A 在这种情况下,可以一次性调用关系数据库,同时检索电影和角色(sql select with join) 我的问题是,在这样的查询中添加过滤器时,如何保持sql性能 案例B 在本例中,我们似乎必须使用FieldResolver执行此操
@Resolver(of => Film)
export class FilmResolvers {
constructor(private readonly filmService: FilmService) {}
@Query(returns => [Film])
async allFilms(@Args() args: QueryAllFilmDTO): Promise<Film[]> {
return this.filmService.findAll(args);
}
}
@Resolver(of => Film)
export class FilmResolvers {
constructor(
private readonly filmService: FilmService,
@InjectRepository(Person) private readonly personRepository: Repository<Person>,
) {}
@ResolveProperty(type => [Person])
async characters(@Parent() film: Film, @Args() args: PersonQueryAllDTO) {
// Low Performance in this case
const persons = await this.personRepository
.createQueryBuilder('person')
.leftJoin('person.films', 'film','film.id = :films_param',{films_param: [film.id]})
.getMany();
return persons;
}
@Query(returns => [Film])
async allFilms(@Args() args: QueryAllFilmDTO): Promise<Film[]> {
this.detectRelation(info.operation.selectionSet);
return this.filmService.findAll(args);
}
}
@Resolver(of=>胶片)
导出类解析程序{
构造器(私有只读电影服务:电影服务){}
@查询(返回=>[Film])
异步allFilms(@Args()Args:QueryAllFilmTo):承诺{
返回此.filmService.findAll(args);
}
}
案例B(扩展实施)
解析程序:
@Resolver(of => Film)
export class FilmResolvers {
constructor(private readonly filmService: FilmService) {}
@Query(returns => [Film])
async allFilms(@Args() args: QueryAllFilmDTO): Promise<Film[]> {
return this.filmService.findAll(args);
}
}
@Resolver(of => Film)
export class FilmResolvers {
constructor(
private readonly filmService: FilmService,
@InjectRepository(Person) private readonly personRepository: Repository<Person>,
) {}
@ResolveProperty(type => [Person])
async characters(@Parent() film: Film, @Args() args: PersonQueryAllDTO) {
// Low Performance in this case
const persons = await this.personRepository
.createQueryBuilder('person')
.leftJoin('person.films', 'film','film.id = :films_param',{films_param: [film.id]})
.getMany();
return persons;
}
@Query(returns => [Film])
async allFilms(@Args() args: QueryAllFilmDTO): Promise<Film[]> {
this.detectRelation(info.operation.selectionSet);
return this.filmService.findAll(args);
}
}
@Resolver(of=>胶片)
导出类解析程序{
建造师(
私人只读电影服务:电影服务,
@InjectRepository(Person)私有只读personRepository:Repository,
) {}
@ResolveProperty(类型=>[Person])
异步字符(@Parent()film:film,@Args()Args:PersonQueryAllTo){
//在这种情况下,性能较低
const persons=wait this.personRepository
.createQueryBuilder(“人员”)
.leftJoin('person.films','film','film.id=:films\u param',{films\u param:[film.id]})
.getMany();
返回人员;
}
@查询(返回=>[Film])
异步所有电影(@Args()Args:queryalFilmDTO):承诺{
此.detectRelation(信息.操作.选择集);
返回此.filmService.findAll(args);
}
}
这里的问题是我们手动连接(两个数据库调用)
我正在考虑其他解决方案,但我需要您的审核:
案例B(其他扩展实施)
我的目标是检索ExtendendGraphQL请求信息,检测查询中的关系,并使用join构造sql查询
@Resolver(of => Film)
export class FilmResolvers {
constructor(
private readonly filmService: FilmService,
@InjectRepository(Person) private readonly personRepository: Repository<Person>,
) {}
@Query(returns => [Film])
async allFilms(@Args() args: QueryAllFilmDTO, @Info() info: GraphQLResolveInfo): Promise<Film[]> {
const relations: string[] = [];
this.getRelations(info.operation.selectionSet, (relation) =>{
relations.push(relation);
});
return this.filmService.findAll(args, relations);
}
private getRelations(selectionSetNode: SelectionSetNode, callback: relationCallback, level=0){
selectionSetNode.selections.forEach( (subSelection) => {
if(subSelection.kind === 'Field'){
const fieldNode = subSelection as FieldNode;
if(fieldNode.selectionSet){
if(level)
callback(fieldNode.name.value);
this.getRelations(fieldNode.selectionSet, callback, ++level);
}
}
});
}
}
@Resolver(of=>胶片)
导出类解析程序{
建造师(
私人只读电影服务:电影服务,
@InjectRepository(Person)私有只读personRepository:Repository,
) {}
@查询(返回=>[Film])
异步所有电影(@Args()Args:queryalfilmdto,@Info()Info:graphqlsolveinfo):承诺{
常量关系:字符串[]=[];
this.getRelations(info.operation.selectionSet,(relations)=>{
关系。推(关系);
});
返回此.filmService.findAll(args,relations);
}
私有getRelations(selectionSetNode:selectionSetNode,回调:relationCallback,级别=0){
selectionSetNode.selections.forEach((子选择)=>{
if(subSelection.kind=='Field'){
const fieldNode=作为fieldNode的子选择;
if(fieldNode.selectionSet){
如果(级别)
回调(fieldNode.name.value);
this.getRelations(fieldNode.selectionSet,回调,++level);
}
}
});
}
}
这是一个好的选择吗?或者有没有其他方法来优化数据库调用
@Resolver(of => Film)
export class FilmResolvers {
constructor(
private readonly filmService: FilmService,
@InjectRepository(Person) private readonly personRepository: Repository<Person>,
) {}
@Query(returns => [Film])
async allFilms(@Args() args: QueryAllFilmDTO, @Info() info: GraphQLResolveInfo): Promise<Film[]> {
const relations: string[] = [];
this.getRelations(info.operation.selectionSet, (relation) =>{
relations.push(relation);
});
return this.filmService.findAll(args, relations);
}
private getRelations(selectionSetNode: SelectionSetNode, callback: relationCallback, level=0){
selectionSetNode.selections.forEach( (subSelection) => {
if(subSelection.kind === 'Field'){
const fieldNode = subSelection as FieldNode;
if(fieldNode.selectionSet){
if(level)
callback(fieldNode.name.value);
this.getRelations(fieldNode.selectionSet, callback, ++level);
}
}
});
}
}