为什么我没有为#Ecto.Query实现协议可枚举?

时间:2016-05-31 14:07:29

标签: elixir phoenix-framework ecto

虽然我将查询传递给受this answer启发的存储库,如下所示:

teams_users = Repo.all (from(t in Team, where: t.owner_id == ^user_id))
    |> Enum.each( &team_users/1 )


def team_users (team) do
    %{id: id} = team
    Repo.all (from(tu in TeamUser, where: tu.team_id == ^id))
end

但是,我收到了这个错误:

[error] GenServer #PID<0.450.0> terminating
** (Protocol.UndefinedError) protocol Enumerable not implemented for #Ecto.Query<from t in App.Team, where: t.owner_id == ^1>
    (elixir) lib/enum.ex:1: Enumerable.impl_for!/1
    (elixir) lib/enum.ex:116: Enumerable.reduce/3
    (elixir) lib/enum.ex:1477: Enum.reduce/3
    (elixir) lib/enum.ex:609: Enum.each/2
    (App) web/channels/user_channel.ex:93: App.UserChannel.handle_in/3
    (phoenix) lib/phoenix/channel/server.ex:223: Phoenix.Channel.Server.handle_info/2
    (stdlib) gen_server.erl:615: :gen_server.try_dispatch/4
    (stdlib) gen_server.erl:681: :gen_server.handle_msg/5
    (stdlib) proc_lib.erl:240: :proc_lib.init_p_do_apply/3

我想要做的是获得所有团队,然后获得每个团队的用户,然后我希望将所有用户放在一个阵列中。

我错过了什么吗?任何建议?有没有更好的方法来实现这一目标?

2 个答案:

答案 0 :(得分:5)

所以这里有一个问题:

teams_users = Repo.all (from(t in Team, where: t.owner_id == ^user_id))
|> Enum.each( &team_users/1 )

您应该删除Repo.all(

之间的空格
teams_users = Repo.all(from(t in Team, where: t.owner_id == ^user_id))
|> Enum.each( &team_users/1 )

您也可以将其写为:

teams_users =
from(t in Team, where: t.owner_id == ^user_id)
|> Repo.all()
|> Enum.each( &team_users/1 )

然而,这样做会引入一个n + 1查询。您将进行一次查询以获取您的团队,然后另一次查询以获取团队用户。您应该查看Repo.preload/2

teams_users =
  from(t in Team, where: t.owner_id == ^user_id)
  |> Repo.all()
  |> Repo.preload(:team_users)

答案 1 :(得分:0)

您正在将查询宏直接传递到Enum.each中,而不是使用Repo.all解决查询并将其发送到Enum中。