Phoenix Ecto上的join和preload有什么区别

问题描述 投票:0回答:1

我对如何在凤凰中使用ecto感到困惑。

我的模式是:

schema "members" do
    field :first_name, :string
    field :last_name, :string
    belongs_to :prefecture, Prefecture

    timestamps()
  end

  schema "prefectures" do
    field :prefecture_name, :string
    has_many :members, Member

    timestamps()
  end

有效的预加载:

def list_members do
    Repo.all(Member)
      |> Repo.preload(:prefecture)
  end

并且在模板中可以用作:

<%= for member <- @members do %>
    <tr>
      <td><%= member.last_name %></td>
      <td><%= member.first_name %></td>
      <td><%= member.perfecture.prefecture_name %></td>
    </tr>
<% end %>

现在使用查询时将不起作用:

def list_members do
    query = from m in Member,
            join: p in Prefecture, on: p.id == m.prefecture_id,
            select: %{last_name: m.last_name , first_name: m.first_name, prefecture_name: p.prefecture_name}
    Repo.all(query)
  end

在模板中以以下方式使用:

<%= for member <- @members do %>
    <tr>
      <td><%= member.last_name %></td>
      <td><%= member.first_name %></td>
      <td><%= member.prefecture_name %></td>
    </tr>
<% end %>

它导致以下错误:

maps cannot be converted to_param. A struct was expected, got: %{first_name: "Boo", last_name: "Muu", prefecture_name: "Japan"}

有什么区别,我应该怎么做才能起作用?我想用JOIN的方式。 (2)

elixir phoenix-framework ecto
1个回答
1
投票

并不是说它不起作用。就像错误指示一样,问题出在结果的格式上。

此代码的结果:

Repo.all(Member) |> Repo.preload(:prefecture)

%Member{}结构的列表。而其他查询的结果是仅包含您选择的内容的地图列表。

因此,错误。它来自您正在使用的URL helper

<%= link "Show", to: Routes.member_path(@conn, :show, member) %>

这些URL帮助器可以根据其应使用的内容(id,slug等)从结构构建URL。但是关键是他们期望一个结构。如果要对第二个查询的结果使用帮助器,则必须将ID直接传递给URL帮助器Routes.member_path,而不是整个member结构。喜欢:

<%= link "Show", to: Routes.member_path(@conn, :show, member.id) %>

为此,您需要在查询的结果图中添加成员的ID:

def list_members do
  query = from m in Member,
          join: p in Prefecture, on: p.id == m.prefecture_id,
          select: %{id: m.id, last_name: m.last_name , first_name: m.first_name, prefecture_name: p.prefecture_name}
  Repo.all(query)
end

这就是如果您使用URL的ID(例如/members/:id),如果您使用的是其他内容,则必须使用该ID。

© www.soinside.com 2019 - 2024. All rights reserved.