首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >我怎样才能让Absinthe和Dataloader一起工作?

我怎样才能让Absinthe和Dataloader一起工作?
EN

Stack Overflow用户
提问于 2020-11-13 18:21:52
回答 1查看 1.1K关注 0票数 5

我有一个使用常规解析函数的GraphQL API,它工作得很好。我的目标是消除N+1问题。

为此,我决定使用Dataloader。据推测,我已经完成了这些步骤来运行这个应用程序:

  1. 我将这两个函数添加到上下文模块:

代码语言:javascript
复制
defmodule Project.People do
  # CRUD...

  def data, do: Dataloader.Ecto.new(Repo, query: &query/2)

  def query(queryable, _params) do
    queryable
  end
end

  1. I向架构模块添加了context/1plugins/0,并更新了用于查询的解析器:

代码语言:javascript
复制
defmodule ProjectWeb.GraphQL.Schema do
  use Absinthe.Schema

  import Absinthe.Resolution.Helpers, only: [dataloader: 1]

  alias ProjectWeb.GraphQL.Schema
  alias Project.People

  import_types(Schema.Types)

  query do
    @desc "Get a list of all people."
    field :people, list_of(:person) do
      resolve(dataloader(People))
    end

    # Other queries...
  end

  def context(context) do
    loader =
      Dataloader.new()
      |> Dataloader.add_source(People, People.data())

    Map.put(context, :loader, loader)
  end

  def plugins, do: [Absinthe.Middleware.Dataloader | Absinthe.Plugin.defaults()]
end

官方教程中没有给出其他步骤。我的:person对象如下所示:

代码语言:javascript
复制
@desc "An object that defines a person."
  object :person do
    field :id, :id
    field :birth_date, :date
    field :first_name, :string
    field :last_name, :string
    field :pesel, :string
    field :second_name, :string
    field :sex, :string

    # field :addresses, list_of(:address) do
    #   resolve(fn parent, _, _ ->
    #     addresses = Project.Repo.all(Ecto.assoc(parent, :addresses))

    #     {:ok, addresses}
    #   end)
    #   description("List of addresses that are assigned to this person.")
    # end

    # field :contacts, list_of(:contact) do
    #   resolve(fn parent, _, _ ->
    #     contacts = Project.Repo.all(Ecto.assoc(parent, :contacts))

    #     {:ok, contacts}
    #   end)
    #   description("List of contacts that are assigned to this person.")
    # end
  end

注释部分是在没有dataloader的情况下工作的解析器,不会导致问题。

当我试图询问:

代码语言:javascript
复制
{
  people { 
    id
  }
}

我明白了:

代码语言:javascript
复制
Request: POST /graphiql
** (exit) an exception was raised:
    ** (Dataloader.GetError)   The given atom - :people - is not a module.

  This can happen if you intend to pass an Ecto struct in your call to
  `dataloader/4` but pass something other than a struct.

我无法完全理解错误消息,因为我将一个模块传递给dataloader/1,无法找到解决方案。可能是什么情况?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-11-13 18:50:16

我已经成功地让这件事成功了--以下是如何做到的:

dataloader本身不知道从数据库中提取什么,它只理解关联。因此,dataloader(People)只能是object块的一部分,而不是query块的一部分。

换言之:

代码语言:javascript
复制
defmodule ProjectWeb.GraphQL.Schema do
  use Absinthe.Schema

  import Absinthe.Resolution.Helpers, only: [dataloader: 1]

  alias ProjectWeb.GraphQL.Schema
  alias Project.People

  import_types(Schema.Types)

  query do
    @desc "Get a list of all people."
    field :people, list_of(:person) do
      resolve(&StandardPerson.resolver/2)
    end

    # Other queries...
  end

  def context(context) do
    loader =
      Dataloader.new()
      |> Dataloader.add_source(People, People.data())

    Map.put(context, :loader, loader)
  end

  def plugins, do: [Absinthe.Middleware.Dataloader | Absinthe.Plugin.defaults()]
end

代码语言:javascript
复制
  @desc "An object that defines a person."
  object :person do
    field :id, :id
    field :birth_date, :date
    field :first_name, :string
    field :last_name, :string
    field :pesel, :string
    field :second_name, :string
    field :sex, :string

    field :addresses, list_of(:address) do
      resolve(dataloader(People))
      description("List of addresses that are assigned to this person.")
    end

    field :contacts, list_of(:contact) do
      resolve(dataloader(People))
      description("List of contacts that are assigned to this person.")
    end
  end
票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/64826080

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档