我如何将苦艾酒数据加载器用于多对多关系

时间:2019-10-13 09:22:02

标签: graphql elixir phoenix-framework absinthe

在我的phoenix应用程序中,在Artist和使用联接表artists_causes实现的Cause模式之间有很多对很多的关系。在我的艺术家模式中,我有many_to_many :causes, Cause, join_through: "artists_causes",在原因模式中,我有many_to_many :artists, Artist, join_through: "artists_causes" 我为graphql使用苦艾酒,并且在我的CauseTypes模块中,我实现了一个cause对象,如下所示:

defmodule MyAppWeb.Schema.CauseTypes do
  @moduledoc """
  All types for causes
  """
  use Absinthe.Schema.Notation
  import Absinthe.Resolution.Helpers, only: [dataloader: 1, dataloader: 3]

  object :cause do
    field :id, :id
    field :artists, list_of(:artist), resolve: dataloader(Artists)
  end

  def dataloader do
    alias MyApp.{Artists, Causes}
    loader = Dataloader.new
    |> Dataloader.add_source(Causes, Causes.datasource())
    |> Dataloader.add_source(Artists, Artists.datasource())
  end

  def context(ctx) do
    Map.put(ctx, :loader, dataloader())
  end

  def plugins do
    [Absinthe.Middleware.Dataloader] ++ Absinthe.Plugin.defaults()
  end
end

据我了解,使用苦艾数据加载器,数据加载器/ 1是我需要加载艺术家列表的。但是,当我在graphiql

中运行以下查询时,无法从得到错误artists: #Ecto.Association.NotLoaded<association :artists is not loaded>的原因中查询艺术家。
query{
 causes{
  id
  artists {
            id
   }
 }
}

在处理多对多关系方面,我缺少任何一点吗?

==========

更新

我更新了list_causes函数,如下所示

def list_causes do    
   Repo.all(MyApp.Causes.Cause) 
end

def list_causes do
    Repo.all(from c in Cause,
    left_join: ac in "artists_causes", on: c.id == ac.cause_id,
    left_join: a in Artist, on: a.id == ac.artist_id,
    preload: [:artists]
    )
  end

and,我现在收到错误FunctionClauseError at POST /graphiql\n\nException:\n\n ** (FunctionClauseError) no function clause matching in anonymous fn/3 in Absinthe.Resolution.Helpers.dataloader/1,它可能指向Absinthe.Resolution.Helpers.dataloader/1方法。我已经导入了助手,还有其他我可能会缺少的东西吗?

1 个答案:

答案 0 :(得分:0)

我认为您必须先与Ecto手动与艺术家建立关系,然后再将其传递给苦艾酒。

例如,获取原因如下:

from(c in Cause,
  preload: [:artists],
  select: c
)
|> Repo.all()

附加

我解决苦艾酒查询的方法。

在查询对象中,我传递了解析器模块功能参考。

resolve(&App.Resolver.get_all_causes/2)

使用解析器功能,我返回数据集

def get_all_causes(_params, _info) do
  {:ok,
   from(c in Cause,
     preload: [:artists],
     select: c
   )
   |> Repo.all()}
end