21

有没有办法在不显式使用 preload: 的情况下预加载 ecto 关联?

类似于架构中的选项?

schema "gadgets" do
  field :foo,
  has_many :bars, Myapp.Bar, preload: true
end

我正在做类似的事情

Repo.get(Gadget, id)
  |> Repo.preload: [:bars]

编辑:我试图这样做的原因是因为我想将相关模型预加载到已经预加载的相关模型中,比如

 preload: [:invoices preload: :items] 
4

2 回答 2

33

您还可以将预加载作为查询的一部分:

defmodule Gadget do
  use Ecto.Model

  # ...

  def with_invoices(query) do
    from q in query, preload: [invoices: :items]
  end
end

然后:

Gadget
|> Gadget.with_invoices
|> Repo.get!(id)
于 2015-04-13T07:12:05.257 回答
-2

我不确定这是最快的方法,但我最终使用了 after_load 回调,如下所示:

defmodule Invoice do
  use Ecto.Model

  after_load :preload_items

  def preload_items(invoice) do
    invoice |> Repo.preload([:items])
  end
end

现在,每次加载 Invoice 时,即使它是由其他东西预加载的,它也会预加载其关联的项目。

编辑 - 不要这样做

而是将预加载放在查询中。使用上述代码检索 1000 张发票将导致 1 + 1000 次查询。查询中的预加载添加了 0NE。询问。1 + 1 < 1000 + 1。

  query = from c in Gadget,
  #retrieve nested associations adds one query
  preload: [invoices: :items]
  select c

Repo.all(query)
于 2015-04-14T04:17:14.207 回答