【问题标题】:Unable to preload multiple-hierarchy model无法预加载多层次模型
【发布时间】:2016-12-20 02:42:42
【问题描述】:

我有3级层次模型关系,即model1属于model2model2属于model3

我正在尝试为model1 预加载model2model3

  my_models = Repo.all(Model1)
    |> Enum.map(fn (x) ->
      Repo.preload(x, :model2)
    end) 
    |> Enum.map(fn(x) -> # error "no function clause matching in Ecto.Repo.Preloader.preload/4"
      Repo.preload(x.model2, :model3)
    end)

错误是“Ecto.Repo.Preloader.preload/4中没有函数子句匹配

【问题讨论】:

  • 你为什么要在Enum.map中预加载?这违背了预加载的全部目的。为什么不Repo.all(Model1) |> Repo.preload(model2: [:model3])
  • @Dogbert,预加载不只对单个实体起作用吗?
  • 不,也适用于列表,还支持有效地加载嵌套关联。
  • @Dogbert,这不起作用,它们没有被预加载。是因为它是从“属于”而不是“has_many”的文档吗?

标签: elixir phoenix-framework ecto


【解决方案1】:

你可以这样做:

my_models = Repo.all(Model1) |> Repo.preload(model2: :model3)

请注意,这与以下内容不同:

my_models = Repo.all(Model1) |> Repo.preload([:model2, :model3])

https://hexdocs.pm/ecto/Ecto.Query.html#preload/3中所述

如果您可以提供更多错误消息,我将能够解释您收到该错误消息的原因。很可能model2(在第二个Enum.map中)是nil,而https://github.com/elixir-ecto/ecto/blob/66e90c97054cd855c7cbb694bc79a0b9313f119b/lib/ecto/repo/preloader.ex#L36只适用于maplist

使用上面的嵌套预加载将为您处理这种情况。

【讨论】:

  • 这不起作用,它们没有被预加载。是因为它是从“属于”而不是“has_many”的文档吗?
  • 这绝对适用于两者。请您提供您的帖子您的架构以及在您的问题中运行Repo.preload(model1, model2: :model3) 的结果以帮助确定问题吗?
  • :model3 没有被加载,我应该有 Model3 -> Model1 "has_many through" 或类似的东西吗?
  • @Joshimari 您如何尝试访问 model3?
  • model1_item.model2.model3.id
【解决方案2】:
Repo.preload([{:model2, :model3}])

应该做的伎俩。您可以将这个结构嵌套到任何您想要的深度。例如。 5 个模型深度:

Repo.preload([
  {:model1, [
    {:model2, [
      {:model3, [
        {:model4, :model5}
      ]}
    ]}
  ]}
])

【讨论】:

【解决方案3】:
Repo.all(from m in Model1, preload: [model2: :model3])

好文章-nested preload in ecto

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-02-21
    • 2021-08-23
    • 2018-10-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多