elixir – 如何将Ecto选择查询到Phoenix中的结构?

我有两个模型,歌曲和投票,歌曲有很多票.我想选择所有歌曲并计算每个歌曲的数量.

使用mix gen任务生成的SongController中的索引操作已被修改为:

def index(conn, _params) do
  query = from s in Song, select: %{id: s.id, name: s.name, artist: s.artist} 
  songs = Repo.all(query)
  render(conn, "index.html", songs: songs)
end

在这种情况下,歌曲包含列表列表.但是在原始的生成函数中,歌曲= Repo.all(Song)它是一个Song结构的列表.

这意味着模板中的song_path函数会中断以下错误消息:maps无法转换为_param.有一个结构,得到:%{艺术家:“Stephen”,id:3,name:“Crossfire”}

当然,我真正想要做的是以某种方式向select语句添加一个num_votes字段,然后以某种方式将一个相应的字段添加到Song结构体中?

首先我们应该添加一个virtual field到歌曲模式,以便它可以用来存储num_votes结果:

defmodule Song do
  use Ecto.Schema

  schema "songs" do
    field :num_votes, :integer, virtual: true
    ...
  end
end

使用Ecto.Query.select/3,Ecto.Query.join/5Ecto.Query.API.count/1的组合,我们可以将计数添加到您用来从查询中选择的地图:

  query = from s in Song,
    left_join: v in assoc(:votes),
    select: %{id: s.id, name: s.name, artist: s.artist, num_votes: count(v.id)} 

然后我们可以使用Kernel.struct将每个项目转换成一个结构体:

  songs =
    query
    |> Repo.all()
    |> Enum.map(fn(song) -> struct(Song, song) end)

这将返回可在视图中使用的歌曲结构列表.

翻译自:https://stackoverflow.com/questions/35678680/how-to-turn-ecto-select-queries-into-structs-in-phoenix

转载注明原文:elixir – 如何将Ecto选择查询到Phoenix中的结构?