注意:这是一个大大简化的示例,但问题是相同的。
我正在尝试使用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查询,但是我不知道如何在我的情况下应用它。
有什么建议吗?
答案 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
字段中指定的解析器。