1

注意:这是一个大大简化的例子,但问题是一样的。

我正在尝试/blog-posts使用 GraphQL 接口包装现有的 HTTP 服务。仅当我传入查询参数时,服务才会在其响应中返回一些额外的数据extra-data=true。所以,

  • GET /blog-posts: 获取 ID 和标题
  • GET /blog-posts?extra-data=true: 获取 ID、标题和extra-data字段

我有一个类似于以下的苦艾酒模式:

query do
  field :blog_posts, non_null(list_of(non_null(:blog_post)))
  resolve &MyAppWeb.Resolvers.Blog.posts/3
end

object :blog_post do
  field :id, non_null(:id)
  field :title, non_null(:string)
  field :extra_data, :string,
    resolve: &MyAppWeb.Resolvers.Blog.post_extra_data/3
end

我的问题是我不知道如何实现extra_data解析器,这样它就不会/blog-posts?extra-data=true在已经调用/blog-posts. 有一个中间件https://hexdocs.pm/absinthe/Absinthe.Middleware.Batch.html旨在帮助解决类似的问题,N+1 查询,但我不知道如何在我的情况下应用它。

有什么建议么?

4

1 回答 1

2

一个可选字段

如果它只是一个额外的字段,您可以在查询中传递一个可选参数:

query do
  field :blog_posts, list_of(:blog_post) do
    arg :extra_data, :boolean
    resolve &MyAppWeb.Resolvers.Blog.posts/2
  end
end

多个额外字段

但是,如果有多个可选参数,最好使用自定义input_object

input_object :extra_input do
  field :extra_a, :boolean
  field :extra_b, :boolean
  field :extra_c, :boolean
end

query do
  field :blog_posts, list_of(:blog_post) do
    arg :extra_fields, :extra_input
    resolve &MyAppWeb.Resolvers.Blog.posts/2
  end
end

在您的解析器中,您可以获取请求字段并使用它们构建您的 HTTP 请求 URL:

def posts(%{extra_fields: extra}, _resolution) do
  # Here `extra` is a map of the optional fields requested. You can
  # filter selected fields, map them to their HTTP service name and
  # construct the HTTP url and query params before calling it in
  # one go
end

在这两种情况下,请删除您直接在对象中的:extra_data字段上指定的解析器:blog_post

于 2018-11-26T00:41:40.270 回答