2015-04-12 70 views
14

有沒有任何方法可以在不明確使用預加載的情況下預加載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] 

回答

29

您還可以預加載作爲查詢的一部分:

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) 
+7

是否有任何理由它不是模式中的選項?我知道在查詢時保留是否預加載是很好的選擇,但對於某些相關模型,您總是需要預加載它。在我的,發票總數是從項目計算的,如果沒有預先加載,這將不起作用。 –

-1

我不知道它是最快的途徑,但最後我做這個使用after_load回調,像這樣:

defmodule Invoice do 
    use Ecto.Model 

    after_load :preload_items 

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

現在,每次發票是裝,即使它是由其他東西預加載的,它也會預載它的相關項目。

編輯 - 不這樣做

把預加載的查詢,而不是。使用上面的代碼檢索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) 
+4

不要這樣做。這將爲每個發票做一個查詢。因此,如果您在查詢中加載10個發票,它將執行10個單獨的查詢來加載項目。 –

+0

謝謝,我知道這是不好的,回答上面編輯 –

+1

回收已從Elixir中刪除 – LukeS