Phoenix Ecto 上的 join 和 preload 有什么区别
What is the difference between join and preload on 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 helper:
<%= link "Show", to: Routes.member_path(@conn, :show, member) %>
这些 URL 助手可以根据他们应该使用的内容(id、slug 等)从结构构建 URL。但关键是他们期望一个结构。如果你想在第二个查询的结果中使用 helper,你必须将 id 直接传递给 URL helper 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
),如果您使用其他东西,则必须改用它。
我对如何在 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 helper:
<%= link "Show", to: Routes.member_path(@conn, :show, member) %>
这些 URL 助手可以根据他们应该使用的内容(id、slug 等)从结构构建 URL。但关键是他们期望一个结构。如果你想在第二个查询的结果中使用 helper,你必须将 id 直接传递给 URL helper 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
),如果您使用其他东西,则必须改用它。