如何解析子字段,以便它们向HTTP查询添加可选参数?

时间:2018-11-25 23:58:26

标签: elixir graphql absinthe

注意:这是一个大大简化的示例,但问题是相同的。

我正在尝试使用GraphQL接口包装现有的HTTP服务/blog-posts。仅当我传入查询参数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查询,但是我不知道如何在我的情况下应用它。

有什么建议吗?

1 个答案:

答案 0 :(得分:2)

一个可选字段

如果这只是一个额外的字段,则可以在查询中传递optional argument

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字段中指定的解析器。