【问题标题】:apollo-server - Conditionally exclude fields from selection setapollo-server - 有条件地从选择集中排除字段
【发布时间】:2020-01-02 07:27:04
【问题描述】:

我有一种情况,我想在点击查询的解析器之前有条件地从查询选择中排除一个字段。

用例是我的底层 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 的字段解析器,并且查询解析器会向底层 API 发出请求,将选择集中的字段(包括无效的 medicareNumber)附加为查询参数。此时 API 调用返回一个错误对象。

我认为这是有道理的,因为指令解析器似乎在 FieldDefinition 上,并且只会在 person 解析器返回有效结果时调用。

有没有办法实现这种功能,有或没有指令?

【问题讨论】:

    标签: apollo apollo-server


    【解决方案1】:

    一般来说,我会警告这种架构设计。作为客户端,如果我在选择集中包含一个字段,我希望在响应中看到该字段——从服务器端的选择集中删除该字段违反规范,并可能导致不必要的混淆(尤其是在更大的团队中)或使用公共 API)。

    如果您正在检查请求的字段以确定要传递给 API 调用的参数,那么强制某个字段解析为 null 不会执行任何操作 - 该字段仍将包含在选择集中。事实上,真的没有办法创建会影响请求选择集的模式指令。

    这里的最佳方法是 1) 确保架构中的任何可能为空的字段都可以为空,以及 2) 显式过滤选择集,无论您的选择集到参数逻辑在哪里。

    编辑:

    架构指令不会显示为info 中返回的架构对象的一部分,因此它们不能用作标志。我的建议是维护一个单独的内存映射。例如:

    const fieldsByLocale = {
      US: {
        Person: ['name', 'medicareNumber'],  
      },
      AU: {
        Person: ['name'],
      },
    }
    

    然后您可以访问适当的列表以使用fieldsByLocale[context.locale][info.returnType] 进行过滤。此过滤逻辑特定于您的数据源(在本例中为外部 API),因此这比使用与存储层有关的信息“污染”模式要干净一些。如果 API 发生变化,或者您完全切换到此信息的不同来源(如数据库),您可以更新解析器而无需修改类型定义。事实上,通过这种方式,过滤逻辑可以轻松地存在于域/服务层而不是解析器中。

    【讨论】:

    • 对,这就是混淆客户的好方法。是否有一种方法可以轻松地标记类型上的字段(类似于指令)并让它们流向选择集?目前,我有一个有点 hacky 的解决方案,它一起遍历 info.selectionSetinfo.schema 树以确定需要过滤选择集中的哪些字段。理想情况下,我想在架构级别标记这些字段。
    • 忘了提到,作为我的指令的SchemaDirectiveVisitor.visitFieldDefinition 覆盖的一部分,我通过在字段上添加_locales 属性来改变info 对象。因此,为什么我能够遍历标记字段的模式。谢谢你的建议。然而,维护一个单独但与我的架构相当耦合的地图似乎很乏味。但它给了我一些想法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-06
    • 2015-04-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多