Ecto 如何过滤 a has many through realtionship

问题描述

我正在学习如何使用 Ecto 编写查询。我想从 has_many through 关系中过滤结果,如果可能的话,通过 Repo.all()数据库进行一次调用

我认为我可以通过使用现有查询组合此查询来做到这一点。例如

def users(organization_id) do
  Repo.get(Organization,organization_id)
   |> Ecto.assoc(:users)
end

def bookings(%{organization_id: organization_id}) do
  Repo.get(Organization,organization_id)
    |> Ecto.assoc(:bookings)
end

然后,重复使用上述之一:

def bookings(%{organization_id: organization_id,user_id: user_id}) do
  Repo.get(Organization,organization_id)
    |> Ecto.assoc(:bookings)
    |> where([u],u.user_id == ^user_id)
end

但这不会按给定的 user_id 过滤结果。如何做呢?我错过了什么?

架构信息:

解决方法

您在追求Ecto.Query.subquery/2。此外,Repo.get/1 已经对数据库执行了查询;在您的情况下,您应该构建查询,然后才执行它。

一个 Organization 可以有多个 Users

也就是说,user_id 表中没有 organizations 这样的字段。为了能够按 users 进行过滤,查询中需要有 users

我相信,按照这些思路是可行的(如果没有看到真正的模式,就不可能准确地判断。)

  users = 
    from o in Organization,join: u in User,on: u.organization_id == o.id,where u.id == ^user_id

  query =
    from u in subquery(users),join: b in Booking,on: b.user_id == u.id

  Repo.all(query)

或者,对于后者,可以使用 Ecto.assoc/2

users
|> Repo.all()
|> Ecto.assoc(:bookings)
|> Repo.all()