GraphQL 查询,具有动态字段

Posted

技术标签:

【中文标题】GraphQL 查询,具有动态字段【英文标题】:GraphQL query, with dynamic fields 【发布时间】:2020-01-30 06:24:15 【问题描述】:

我有这样的架构类型:

type Instance 
  id: ID!
  parentSeries: ID
  tags: JSON

标签字段是动态 JSON 类型 (https://github.com/taion/graphql-type-json)。它也非常大。理想情况下,在客户端上,我可以使用我返回的标签指定哪些字段。 GraphQL/Apollo 可以做到这一点吗?如果没有,你有什么建议?

【问题讨论】:

【参考方案1】:

您可以在 tags 中添加参数,例如路径或其他类型的过滤器:

type Instance 
  id: ID!
  parentSeries: ID
  tags(path:String): JSON

然后像@Daniel Rearden 的回答那样在你的解析器中实现过滤器

但是!为什么要用一个巨大的 json 来设计它???

通常我在只有少量东西并且在编译时无法确定数据的“形状”时使用 JSON。或者只是服务器不关心数据的内容,客户端会做所有的工作。

在您的情况下,JSON 数据确实很大,那么我想将其分解为更小的类型会是更好的方法

【讨论】:

谢谢。不幸的是,此时我不一定控制这个巨大的 JSON 响应的形状。我很想,但我现在不能。也许我可以将这个巨大的 JSON 包装在一个包装器类型中,它会公开一些我需要的字段,并在它们稳定后逐渐添加它们。【参考方案2】:

您可以在字段中包含path 参数,然后使用lodashget 之类的东西根据提供的路径转换JSON 项:

const resolvers = 
  Instance: 
    tags: (instance, args) => 
      return _.get(instance.tags, args.path)
    ,
  ,

您可以通过这种方式应用任意数量的任意转换来自定义返回的 JSON 对象。但是,由于您要返回一个标量,因此无法只为该字段提供一个选择集。

人们常常觉得他们需要使用 JSON 标量仅仅是因为他们使用的数据是一张地图。但是,可以轻松地将地图转换为数组,无需 JSON 标量即可轻松地在您的模式中表示。所以你可以转这个:


  "foo": 
    "propA": "A",
    "propA": "B"
  ,
  "bar": 
    "propA": "A"
    "propA": "B"
  

进入这个:

[
  
    "tagName": "foo",
    "propA": "A",
    "propA": "B"
  ,
  
    "tagName": "bar",
    "propA": "A",
    "propA": "B"
  
]

【讨论】:

路径参数在某种意义上是一个字符串“getter”,是吗?有没有办法获得原生的 graphql 查询语法?转换成数组是一个有趣的想法。正如您所说,这简化了我的架构(我可以取消 json 类型)。但是在查询结束时会给我带来什么? WRT "native graphQL syntax",就像我说的那样,因为您使用的是标量,所以无法为该字段提供子选择(即一个或多个子字段)。不管后端如何序列化标量,根据定义,它不能有子字段(与对象类型不同,它可以)。将数据转换为数组意味着您现在可以tags 字段提供字段的子选择,因为您的类型现在将是某个对象类型的列表。 如果您最终使用了一个列表,值得注意的是,如果需要这种行为,您可以轻松添加 tagNames 参数来过滤特定标签。 这将是我的下一个问题(过滤)。谢谢丹尼尔,这很有帮助

以上是关于GraphQL 查询,具有动态字段的主要内容,如果未能解决你的问题,请参考以下文章

具有动态键的对象的 Apollo/GraphQL 字段类型

具有动态键的对象的 Apollo/GraphQL 字段类型

具有动态键的对象的 Apollo/GraphQL 字段类型

如何使用 Apollo graphql 动态调整查询形状(字段)?

具有多个嵌套解析器并将字段映射到参数的 GraphQL 查询

在 reactJS 中使用动态字段的 Apollo 客户端 graphql 查询