GraphQL查询,带有动态字段

GraphQL查询,带有动态字段,graphql,apollo,Graphql,Apollo,我有这样一种模式类型: type Instance { id: ID! parentSeries: ID tags: JSON } 标记字段是动态JSON类型。它也非常大。理想情况下,在客户机上,我可以指定使用标记返回的字段。这在GraphQL/Apollo上可能吗?如果没有,您会有什么建议?您可以在字段中包含一个path参数,然后使用lodash's get之类的方法根据提供的路径转换JSON项: const resolvers = { Instance: { tag

我有这样一种模式类型:

type Instance {
  id: ID!
  parentSeries: ID
  tags: JSON
}
标记字段是动态JSON类型。它也非常大。理想情况下,在客户机上,我可以指定使用标记返回的字段。这在GraphQL/Apollo上可能吗?如果没有,您会有什么建议?

您可以在字段中包含一个path参数,然后使用lodash's 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"
  }
]

您可以在标记中添加参数,如path或其他类型的过滤器:

type Instance {
  id: ID!
  parentSeries: ID
  tags(path:String): JSON
}
然后在解析器中实现过滤器,如@Daniel Rearden的答案

然而!为什么要用一个巨大的json来设计它

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


在您的例子中,JSON数据非常庞大,那么我想将其拆分为较小的类型将是一种更好的方法

从某种意义上讲,path参数将是字符串获取器是吗?是否仍然可以获取本机graphql查询语法?转换为数组是一个有趣的想法。这简化了我的模式,正如您所说,我可以去掉json类型。但是在查询端这能给我带来什么呢?WRT原生graphQL语法,正如我所说的,因为您使用的是标量,所以无法提供子选择,即字段的一个或多个子字段。无论标量是如何由后端序列化的,根据定义,标量不能具有与对象类型不同的子字段,而对象类型可以。将数据转换为数组意味着您现在可以为标记字段提供字段的子选择,因为您的类型现在将是某个对象类型的列表。如果您最终使用列表,值得注意的是,如果需要,您可以轻松添加标记名参数来筛选特定标记。这将是我的下一个问题筛选。谢谢丹尼尔,那很有用谢谢。不幸的是,此时我不一定能控制这个巨大的JSON响应的形状。我很想去,但现在不行。也许我可以将这个巨大的JSON封装在一个包装器类型中,公开我需要的一些字段,并在它们稳定后逐渐添加它们。