在Ecto中嵌套预加载

时间:2016-07-01 11:18:43

标签: elixir phoenix-framework ecto

我正在尝试在ecto中编写一个嵌套查询,它从post表中预加载comments,然后在单独的查询中为每个注释预加载user。这看起来像:

post = Repo.preload(Repo.get(Post, id), [:comments])
comments = Repo.preload(post.comments, [:user])

这个问题是,当我知道有一种方法可以在一个查询中加载我需要的所有数据时,它会在数据库上运行3个不同的查询。

是否与join: assoc()有关?

2 个答案:

答案 0 :(得分:1)

(我在这里提出一个迟到的答案仅供我自己参考。)你可以试试这个:

Repo.preload(Repo.get(Post, id), [{:comments, :user}]).comments

或等效地,以下任何一种:

Repo.preload(Repo.get(Post, id), [comments: :user]).comments
Repo.preload(Repo.get(Post, id), comments: :user).comments

This blog post by tkowal对构造嵌套预加载的语法有很好的解释。 This discussion between José Valim and a netizen也很有用。

答案 1 :(得分:0)

我不认为有一种方法可以用一个查询来做到这一点,据我所知,你必须加入评论和用户到帖子,如果有,比方说,50条评论,你会有50行,其中有相同的用户,我不知道这是否适合你。我认为你可以用2个查询来做到这一点,它会是这样的:

comments_query = 
  Comment
  |> join(:inner, [c], u in assoc(c, :user))
  |> preload([c, u], user: u)
post = Repo.preload(Repo.get(Post, id), comments: comments_query)

我没有对代码进行过测试,但我相信它应该可行,或者至少可以得到一般的想法。