apollo-server - 有条件地从选择集中排除字段
apollo-server - Conditionally exclude fields from selection set
我有一种情况,我想在我点击查询的解析器之前有条件地从查询选择中排除一个字段。
用例是我的底层 API 仅根据用户的语言环境公开某些 'fields',如果请求的字段是不包括在该语言环境中。
我尝试过使用指令的方法,
type Person {
id: Int!
name: String!
medicare: String @locale(locales: ["AU"])
}
type query {
person(id: Int!): Person
}
并使用 SchemaDirectiveVisitor.visitFieldDefinition
,当用户区域设置与指令。
但是,当具有非 "AU"
语言环境的客户端执行以下操作时
query {
person(id: 111) {
name
medicareNumber
}
}
}
从未调用 medicare
的字段解析器,查询解析器向基础 API 发出请求,附加选择集中的字段(包括无效的 medicareNumber
)作为查询参数。 API 此时调用 return 是一个错误对象。
我相信这是有道理的,因为指令解析器似乎在 FieldDefinition
上,并且只有在 person
解析器 return 是有效结果时才会被调用。
有没有办法实现这种功能,有或没有指令?
总的来说,我会提防这种模式设计。作为客户,如果我在选择集中包含一个字段,我希望在响应中看到该字段——从服务器端的选择集中删除该字段违反了规范,并可能导致不必要的混淆(尤其是在较大的团队中或 public API).
如果您正在检查请求的字段以确定要传递给您的 API 调用的参数,那么强制某个字段解析为 null 不会做任何事情 - 该字段仍然是包含在选择集中。事实上,确实没有办法创建会影响请求选择集的模式指令。
这里最好的方法是 1) 确保任何可能为 null 的字段在架构中都可以为 null 和 2) 在您的选择集到参数逻辑所在的位置显式过滤选择集。
编辑:
架构指令不会显示为 info
中返回的架构对象的一部分,因此它们不能用作标志。我的建议是维护一个单独的内存映射。例如:
const fieldsByLocale = {
US: {
Person: ['name', 'medicareNumber'],
},
AU: {
Person: ['name'],
},
}
然后您可以访问适当的列表以使用 fieldsByLocale[context.locale][info.returnType]
进行过滤。此过滤逻辑特定于您的数据源(在本例中为外部 API),因此这比 "polluting" 具有与存储层相关信息的架构更清晰。如果 APIs 发生变化,或者您完全切换到此信息的不同来源(如数据库),您可以更新解析器而无需触及您的类型定义。事实上,通过这种方式,过滤逻辑可以很容易地存在于 domain/service 层中,而不是你的解析器中。
我有一种情况,我想在我点击查询的解析器之前有条件地从查询选择中排除一个字段。
用例是我的底层 API 仅根据用户的语言环境公开某些 'fields',如果请求的字段是不包括在该语言环境中。
我尝试过使用指令的方法,
type Person {
id: Int!
name: String!
medicare: String @locale(locales: ["AU"])
}
type query {
person(id: Int!): Person
}
并使用 SchemaDirectiveVisitor.visitFieldDefinition
,当用户区域设置与指令。
但是,当具有非 "AU"
语言环境的客户端执行以下操作时
query {
person(id: 111) {
name
medicareNumber
}
}
}
从未调用 medicare
的字段解析器,查询解析器向基础 API 发出请求,附加选择集中的字段(包括无效的 medicareNumber
)作为查询参数。 API 此时调用 return 是一个错误对象。
我相信这是有道理的,因为指令解析器似乎在 FieldDefinition
上,并且只有在 person
解析器 return 是有效结果时才会被调用。
有没有办法实现这种功能,有或没有指令?
总的来说,我会提防这种模式设计。作为客户,如果我在选择集中包含一个字段,我希望在响应中看到该字段——从服务器端的选择集中删除该字段违反了规范,并可能导致不必要的混淆(尤其是在较大的团队中或 public API).
如果您正在检查请求的字段以确定要传递给您的 API 调用的参数,那么强制某个字段解析为 null 不会做任何事情 - 该字段仍然是包含在选择集中。事实上,确实没有办法创建会影响请求选择集的模式指令。
这里最好的方法是 1) 确保任何可能为 null 的字段在架构中都可以为 null 和 2) 在您的选择集到参数逻辑所在的位置显式过滤选择集。
编辑:
架构指令不会显示为 info
中返回的架构对象的一部分,因此它们不能用作标志。我的建议是维护一个单独的内存映射。例如:
const fieldsByLocale = {
US: {
Person: ['name', 'medicareNumber'],
},
AU: {
Person: ['name'],
},
}
然后您可以访问适当的列表以使用 fieldsByLocale[context.locale][info.returnType]
进行过滤。此过滤逻辑特定于您的数据源(在本例中为外部 API),因此这比 "polluting" 具有与存储层相关信息的架构更清晰。如果 APIs 发生变化,或者您完全切换到此信息的不同来源(如数据库),您可以更新解析器而无需触及您的类型定义。事实上,通过这种方式,过滤逻辑可以很容易地存在于 domain/service 层中,而不是你的解析器中。