NestJS GraphQL 联合循环解析器
NestJS GraphQL federation circular resolvers
我正在处理现有的 GraphQL 服务,我已使用 apollo 联合成功地将其分解为更小的服务。我有一些类型被其他服务扩展,一切正常。但是,正如我遵循的示例:https://docs.nestjs.com/graphql/federation 现在我遇到了循环引用类型的问题。
基本上我有两种类型:
@ObjectType()
@Directive('@key(fields: "id")')
export class Original {
@Field(type => ID)
id: string;
...
}
// extending it in the other service
@ObjectType()
@Directive('@extends')
@Directive('@key(fields: "id")')
export class Original {
@Field(type => ID)
@Directive('@external')
id: string;
@Field(type => [Other])
@Directive('@requires(fields: "id")')
others: Other[];
...
}
@ObjectType()
@Directive('@key(fields: "id")')
export class Other {
@Field(type => ID)
id: string;
...
@Field(type => Original, { nullable: true })
original?: Original;
}
我有两个解析器,都在扩展原始类型的服务中:
@Resolver(of => Original)
export class OriginalResolver {
...
@ResolveField(returns => [Other])
async others(@Parent() original: Original) {
const { id} = original;
...
}
}
@Resolver(of => Other)
export class OtherResolver {
...
@ResolveField((of) => Original)
async original(@Parent() other: Other) {
return { __typename: 'Orignal', id: other.original.id };
}
}
正如解析器所建议的,我可以用这样的方式进行查询:
...,
original{
others{
original{
*and so on...*
}
}
}
我不希望这个循环查询成为可能,我正在尝试将其删除,但到目前为止我还没有成功。如果我简单地删除“原始”字段解析器,它应该 return __typename,apollo 将不再扩展原始类型。我想那条线基本上是连接两个服务以找到原始类型的,但到目前为止我对 apollo 的了解还不深...
所以我的问题是我怎样才能一起删除那个解析器,或者如果它必须在那里才能让 apollo 工作,有什么办法可以“隐藏它”吗?
在此先致谢,欢迎随时询问您可能需要的更多信息。
在 GraphQL 中 'loops' 是完全合法的(注意 'graph')。 GraphQL 'by design' 提供了自由塑造查询 [和响应结构] 的能力,包括 'loops' 创建。
我不会说是 'circular reference kind of problem'。这可能是一个 efficiency/performance 问题...... **这不是邪恶...... 当不被滥用时。
您可以使用一些指标来限制API使用,限制'max resolving depth level'/等等
在这种情况下,当parent
是others
类型时,您可以在original
解析器中简单地return null
。这样original
只能在查询top/root级别查询。
我正在处理现有的 GraphQL 服务,我已使用 apollo 联合成功地将其分解为更小的服务。我有一些类型被其他服务扩展,一切正常。但是,正如我遵循的示例:https://docs.nestjs.com/graphql/federation 现在我遇到了循环引用类型的问题。
基本上我有两种类型:
@ObjectType()
@Directive('@key(fields: "id")')
export class Original {
@Field(type => ID)
id: string;
...
}
// extending it in the other service
@ObjectType()
@Directive('@extends')
@Directive('@key(fields: "id")')
export class Original {
@Field(type => ID)
@Directive('@external')
id: string;
@Field(type => [Other])
@Directive('@requires(fields: "id")')
others: Other[];
...
}
@ObjectType()
@Directive('@key(fields: "id")')
export class Other {
@Field(type => ID)
id: string;
...
@Field(type => Original, { nullable: true })
original?: Original;
}
我有两个解析器,都在扩展原始类型的服务中:
@Resolver(of => Original)
export class OriginalResolver {
...
@ResolveField(returns => [Other])
async others(@Parent() original: Original) {
const { id} = original;
...
}
}
@Resolver(of => Other)
export class OtherResolver {
...
@ResolveField((of) => Original)
async original(@Parent() other: Other) {
return { __typename: 'Orignal', id: other.original.id };
}
}
正如解析器所建议的,我可以用这样的方式进行查询:
...,
original{
others{
original{
*and so on...*
}
}
}
我不希望这个循环查询成为可能,我正在尝试将其删除,但到目前为止我还没有成功。如果我简单地删除“原始”字段解析器,它应该 return __typename,apollo 将不再扩展原始类型。我想那条线基本上是连接两个服务以找到原始类型的,但到目前为止我对 apollo 的了解还不深...
所以我的问题是我怎样才能一起删除那个解析器,或者如果它必须在那里才能让 apollo 工作,有什么办法可以“隐藏它”吗?
在此先致谢,欢迎随时询问您可能需要的更多信息。
在 GraphQL 中 'loops' 是完全合法的(注意 'graph')。 GraphQL 'by design' 提供了自由塑造查询 [和响应结构] 的能力,包括 'loops' 创建。
我不会说是 'circular reference kind of problem'。这可能是一个 efficiency/performance 问题...... **这不是邪恶...... 当不被滥用时。
您可以使用一些指标来限制API使用,限制'max resolving depth level'/等等
在这种情况下,当parent
是others
类型时,您可以在original
解析器中简单地return null
。这样original
只能在查询top/root级别查询。