我遇到这样一种情况:在查询的解析器之前,我想有条件地从查询选择中排除一个字段。
用例是,我的底层API仅根据用户的区域设置公开特定的“字段”,如果请求的字段没有包含在该区域设置中,则对此API的调用将抛出错误。
我尝试了一种使用指令的方法,
type Person {
id: Int!
name: String!
medicare: String @locale(locales: ["AU"])
}
type query {
person(id: Int!): Person
}使用SchemaDirectiveVisitor.visitFieldDefinition,当用户区域设置与指令中定义的任何区域设置都不匹配时,我覆盖medicare字段的field.resolve以返回null。
但是,当使用非"AU"语言环境的客户端执行以下操作时
query {
person(id: 111) {
name
medicareNumber
}
}
}永远不会调用medicare的字段解析器,查询解析器向底层medicareNumber发出请求,将选择集中的字段(包括无效的API )作为查询参数追加。此时,API调用返回一个错误对象。
我相信这是有意义的,因为指令解析器似乎在FieldDefinition上,并且只有在person解析器返回有效结果时才会被调用。
有没有一种方法可以实现这种功能,不管有没有指令?
发布于 2019-08-29 19:26:32
一般来说,我会告诫不要进行这种模式设计。作为客户机,如果我在选择集中包含一个字段,我希望在响应中看到该字段--从服务器端的选择集中删除该字段是违反规范的,并且可能导致不必要的混乱(特别是在较大的团队或使用公共API时)。
如果您正在检查请求的字段以确定要传递给API调用的参数,那么强制某个字段解析为null不会有任何作用--该字段仍将包含在选择集中。事实上,实际上没有办法创建一个会影响请求选择集的模式指令。
这里最好的方法是: 1)确保模式中任何可能为空的字段都可以为空;2)无论选择集到参数逻辑在哪里,都显式地过滤选择集。
编辑:
模式指令不会作为info中返回的模式对象的一部分出现,因此它们不能用作标志。我的建议是维护一个单独的内存映射。例如:
const fieldsByLocale = {
US: {
Person: ['name', 'medicareNumber'],
},
AU: {
Person: ['name'],
},
}然后,您只需访问适当的列表即可使用fieldsByLocale[context.locale][info.returnType]进行过滤。此过滤逻辑特定于您的数据源(在本例中为外部API),因此这比用属于存储层的信息“污染”模式要干净一些。如果API发生变化,或者您完全切换到此信息的不同来源(如数据库),则可以在不接触类型定义的情况下更新解析器。实际上,通过这种方式,过滤逻辑可以很容易地存在于域/服务层中,而不是您的解析器中。
https://stackoverflow.com/questions/57703062
复制相似问题