【问题标题】:How can I preload association and get it returned in ecto?如何预加载关联并使其在 ecto 中返回?
【发布时间】:2016-10-06 13:00:13
【问题描述】:

假设我有一个 User 模型 has_many Post

我获取了一个用户:

user = Repo.get(User, 1)

现在我想获取该用户的所有帖子。我找到的唯一解决方案是:

posts = Repo.preload(user, :posts).posts

但这很丑。有什么简写吗?

【问题讨论】:

    标签: elixir ecto


    【解决方案1】:
    user = Repo.get(User, 1) |> Repo.preload([:posts])
    

    【讨论】:

    • 虽然这段代码可能会回答这个问题,但通常认为添加对代码作用的解释是一种很好的做法。这使得不熟悉该领域的开发人员能够了解代码中发生了什么,并帮助他们学习如何在未来自行解决问题。
    【解决方案2】:

    您可以使用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]
    ...
    

    【讨论】:

    • assocpreload 有什么区别?
    • assoc 为特定关联构建查询而不从 db 中检索数据,preload 从 db 中检索数据以进行关联,包括嵌套关联。
    • 请注意,preload/2 在一个数据结构中返回父记录(本例中为用户)和关联记录(帖子),而通过管道传送到 Repo.allassoc/2 仅返回关联记录(帖子)。这意味着如果您需要父记录,您可以分别get 它们(如上例所示),但如果您将其完全编写为管道语句,您将不会拥有该数据。
    【解决方案3】:
    user = Repo.get(User, 1) |> preload(:posts)
    

    是你的case的简写

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-04-20
      • 2015-06-18
      • 1970-01-01
      相关资源
      最近更新 更多