Phoenix Ecto上的联接和预加载之间有什么区别



我对如何在phoenix中使用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(

这并不是说它不起作用。正如错误所指出的,问题出在结果的格式上。

此代码的结果:

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

%Member{}结构的列表。而另一个查询的结果是一个地图列表,其中只包含您选择的内容。

因此,出现了错误。它来自您正在使用的URL帮助程序:

<%= 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(,如果你使用其他东西,你就必须使用它。

最新更新