【发布时间】:2016-10-06 13:00:13
【问题描述】:
假设我有一个 User 模型 has_many Post。
我获取了一个用户:
user = Repo.get(User, 1)
现在我想获取该用户的所有帖子。我找到的唯一解决方案是:
posts = Repo.preload(user, :posts).posts
但这很丑。有什么简写吗?
【问题讨论】:
假设我有一个 User 模型 has_many Post。
我获取了一个用户:
user = Repo.get(User, 1)
现在我想获取该用户的所有帖子。我找到的唯一解决方案是:
posts = Repo.preload(user, :posts).posts
但这很丑。有什么简写吗?
【问题讨论】:
user = Repo.get(User, 1) |> Repo.preload([:posts])
【讨论】:
您可以使用Ecto.assoc/2 获取所有帖子的查询,然后将其传递给Repo.all/1 以实际获取它们:
iex(1)> user = Repo.get(User, 1)
iex(2)> Ecto.assoc(user, :posts)
#Ecto.Query<from p in MyApp.Post, where: p.user_id == ^1>
iex(3)> Ecto.assoc(user, :posts) |> Repo.all
[debug] QUERY OK source="posts" db=2.4ms
SELECT p0."id", p0."title", p0."user_id", p0."inserted_at", p0."updated_at" FROM "posts" AS p0 WHERE (p0."user_id" = $1) [1]
...
【讨论】:
assoc 和preload 有什么区别?
assoc 为特定关联构建查询而不从 db 中检索数据,preload 从 db 中检索数据以进行关联,包括嵌套关联。
preload/2 在一个数据结构中返回父记录(本例中为用户)和关联记录(帖子),而通过管道传送到 Repo.all 的 assoc/2 仅返回关联记录(帖子)。这意味着如果您需要父记录,您可以分别get 它们(如上例所示),但如果您将其完全编写为管道语句,您将不会拥有该数据。
user = Repo.get(User, 1) |> preload(:posts)
是你的case的简写
【讨论】: