【问题标题】:Ecto: How to preload records with selecting another joined columnsEcto:如何通过选择另一个连接列来预加载记录
【发布时间】:2018-07-11 10:42:41
【问题描述】:

有没有办法通过选择另一个连接的列来预加载记录?

# table structure
# User 1---* Post 1---* PostTag *---1 Tag

# extract definition of scheme
scheme "posts" do
 ...
 has_many :post_tags, PostTag
 has_many :tags, [:post_tags, :tag]
end

以下伪代码表达了我的目标(但不起作用)。

query = from post in Post,
  join: user in User, on post.user_id == user.id,
  select: %{
    id: post.id,
    title: post.title,
    user_name: user.name, # <= column at joined table
  },
  preload: [:tags]
Repo.all(query)
#=> ** (Ecto.QueryError) the binding used in `from` must be selected in `select` when using `preload` in query:`

我期待这样的结果。

[
  %{id: 1, title: "AAA", user_name: "John", tags: [%{name: "elixir"},...]},
  %{id: 2, title: "BBB", user_name: "Mike", tags: [%{name: "erlang"},...]},
  ...
]

【问题讨论】:

    标签: elixir phoenix-framework ecto


    【解决方案1】:

    正如错误信息所说,你需要在预加载时选择你在from中给出的绑定,否则Ecto没有地方放置预加载的标签。这是一个简单的答案:

    query = from post in Post,
      join: user in User, on: post.user_id == user.id,
      select: {post, user.name},
      preload: [:tags]
    

    通过返回一个元组,您可以将完整的帖子和用户名放在一边。另一种方法是将帖子和用户作为完整结构返回:

    query = from post in Post,
      join: user in User, on: post.user_id == user.id,
      preload: [:tags, user: user]
    

    或者如果您不想要所有字段:

    query = from post in Post,
      join: user in User, on: post.user_id == user.id,
      preload: [:tags, user: user],
      select: [:id, :title, :user_id, user: [:name]]
    

    【讨论】:

    • 我可以像user一样过滤预加载的多条记录(例如:tags)吗?我尝试使用自定义查询tag_q = from tag in Tag, select: [:id, :name],并通过预加载部分(preload: [tags: ^tag_q])。这可以运行,但标签字段不会被过滤。
    • 您可以为用户做同样的事情:select: [:id, :title, :user_id, user: [:name], tags: [:id, :name]]。查询也应该有效。
    • 非常感谢。这正是我想做的。当我尝试select: [:id, :user_id, user: [:name], tags: [:name]] 时,我得到 NoPrimaryKeyValueError。但我认为这不是一个大问题。我可以通过select: [:id, :user_id, user: [:id, :name], tags: [:name]] 得到想要的结果。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-11
    • 2021-08-05
    相关资源
    最近更新 更多