Предварительная загрузка ассоциаций 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)