以编程方式预加载 has_many,通过:在 Elixir Ecto 中
Programmatically Preload has_many, through: in Elixir Ecto
我正在尝试以编程方式将预加载附加到我的一个具有 has_many, through:
关系的模型的查询中。
我的模块:
defmodule MyApp.Chemical do
use MyApp.Web, :model
schema "chemicals" do
has_many :company_chemicals, MyApp.CompanyChemical
has_many :companies, through: [:company_chemicals, :companies]
field :name, :string
end
def with_companies(query) do
from chem in query,
left_join: comp_chem in assoc(chem, :company_chemicals),
join: company in assoc(comp_chem, :company),
preload: [companies: company]
end
end
defmodule MyApp.Company do
use MyApp.Web, :model
schema "companies" do
has_many :company_chemicals, MyApp.CompanyChemical
has_many :chemicals, through: [:company_chemicals, :chemicals]
field :name, :string
end
end
defmodule MyApp.CompanyChemical do
use MyApp.Web, :model
schema "company_chemicals" do
belongs_to :chemical, MyApp.Chemical
belongs_to :company, MyApp.Company
end
end
使用这些模型,MyApp.Chemical.with_companies/1
会按预期工作,返回一个查询,该查询将生成具有已填充 :companies
字段的 Chemical,但我试图创建如下所示的函数以编程方式预加载通过关联的字段 table:
def preload_association(query, local_assoc, assoc_table, assoc_table_assoc) do
from orig in query,
left_join: association_table in assoc(orig, ^assoc_table),
join: distal in assoc(association_table, ^assoc_table_assoc),
preload: [{^local_assoc, distal}]
end
但是,由于 preload: [{^local_assoc, distal}]
行,此函数将无法编译。
如何预加载一个 has_many 的关联?谢谢。
您是否以任何方式过滤您的加入?因为,如果你不是,你应该改为调用 preload:
query = from c in MyApp.Company, where: ...
companies = Repo.all(query)
companies_with_chemicals = Repo.preload(companies, :chemicals)
或:
query = from c in MyApp.Company, preload: :chemicals
companies_with_chemicals = Repo.all(query)
它也会更快,因为它执行两个单独的查询,将要处理的总结果集大小从 companies_size * chemicals_size
减少到 companies_size + chemicals_size
。
请注意,您也应该可以加入 has_many :through
。
我正在尝试以编程方式将预加载附加到我的一个具有 has_many, through:
关系的模型的查询中。
我的模块:
defmodule MyApp.Chemical do
use MyApp.Web, :model
schema "chemicals" do
has_many :company_chemicals, MyApp.CompanyChemical
has_many :companies, through: [:company_chemicals, :companies]
field :name, :string
end
def with_companies(query) do
from chem in query,
left_join: comp_chem in assoc(chem, :company_chemicals),
join: company in assoc(comp_chem, :company),
preload: [companies: company]
end
end
defmodule MyApp.Company do
use MyApp.Web, :model
schema "companies" do
has_many :company_chemicals, MyApp.CompanyChemical
has_many :chemicals, through: [:company_chemicals, :chemicals]
field :name, :string
end
end
defmodule MyApp.CompanyChemical do
use MyApp.Web, :model
schema "company_chemicals" do
belongs_to :chemical, MyApp.Chemical
belongs_to :company, MyApp.Company
end
end
使用这些模型,MyApp.Chemical.with_companies/1
会按预期工作,返回一个查询,该查询将生成具有已填充 :companies
字段的 Chemical,但我试图创建如下所示的函数以编程方式预加载通过关联的字段 table:
def preload_association(query, local_assoc, assoc_table, assoc_table_assoc) do
from orig in query,
left_join: association_table in assoc(orig, ^assoc_table),
join: distal in assoc(association_table, ^assoc_table_assoc),
preload: [{^local_assoc, distal}]
end
但是,由于 preload: [{^local_assoc, distal}]
行,此函数将无法编译。
如何预加载一个 has_many 的关联?谢谢。
您是否以任何方式过滤您的加入?因为,如果你不是,你应该改为调用 preload:
query = from c in MyApp.Company, where: ...
companies = Repo.all(query)
companies_with_chemicals = Repo.preload(companies, :chemicals)
或:
query = from c in MyApp.Company, preload: :chemicals
companies_with_chemicals = Repo.all(query)
它也会更快,因为它执行两个单独的查询,将要处理的总结果集大小从 companies_size * chemicals_size
减少到 companies_size + chemicals_size
。
请注意,您也应该可以加入 has_many :through
。