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
参数,然后使用lodash
的get
之类的东西根据提供的路径转换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 动态调整查询形状(字段)?