Предварительная загрузка ассоциаций Ecto по умолчанию

Есть ли способ предварительно загрузить 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] 

Ответы

Ответ 1

Вы также можете предварительно загрузить как часть запроса:

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)

Ответ 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)