从 Ecto 查询映射到关键字列表

Map from Ecto query into Keyword List

我从 Rails 世界的 Ruby 进入了 Elixir。

我有以下 table:

 release_track_id | release_id | track_id | release_side_id | track_number
------------------+------------+----------+-----------------+--------------
              347 |         70 |      211 |               3 |            1
              329 |         70 |      193 |               1 |            1
              356 |         70 |      220 |               4 |            1
              338 |         70 |      202 |               2 |            1
              357 |         70 |      221 |               4 |            2
              330 |         70 |      194 |               1 |            2
              348 |         70 |      212 |               3 |            2
              339 |         70 |      203 |               2 |            2
              331 |         70 |      195 |               1 |            3
              349 |         70 |      213 |               3 |            3
              358 |         70 |      222 |               4 |            3

到目前为止,要提取的查询效果很好:

query = from at in ReleaseTrack,
      distinct: true,
      join: s in ReleaseSide, on: [release_side_id: s.release_side_id],
      join: a in Release, on: [release_id: at.release_id],
      where: a.active == true,
      where: at.release_id == ^release_id,

Repo.all(query) 

我完美地获得了所有这些行。

但是,我想转换输出的内容:

[
  %App.ReleaseTrack{
    __meta__: #Ecto.Schema.Metadata<:loaded, "release_tracks">,
    inserted_at: ~N[2021-05-26 00:30:34],
    release_id: 70,
    release_side_id: 1,
    release_sides: %App.ReleaseSide{
      __meta__: #Ecto.Schema.Metadata<:loaded, "release_sides">,
      inserted_at: ~N[2021-05-26 00:30:34],
      order_number: 1,
      release: #Ecto.Association.NotLoaded<association :release is not loaded>,
      release_id: 70,
      release_side: "Disc 1",
      release_side_id: 1,
      updated_at: ~N[2021-05-26 00:30:34]
    },
    release_track_id: 329,
    track: %App.Track{
      __meta__: #Ecto.Schema.Metadata<:loaded, "tracks">,
      track_id: 211,
      bpm: 60,
      title: "Ghosts",
      ...
     }
   ],
   ...

我想做的是将 Repo.all 变成这样的东西:

%{ 70 => [track1, track2, track3] %}

如果release_side_id指向Disc 1,如上面的输出,而[track1, track2, track3]代表每个%App.Track{}结果。

本质上,关键字对查看 table:

%{ release_side_id => [track_id data, track_id data] }

无论我不能做什么,我都无法让它发挥作用。在 Ruby 世界中:

tracks = {}

results.each do |result|
  side_name = result["release_side_id"]
  tracks[:release_side_id] ||= []
  tracks[:release_side_id] << results["track_id"]
end

我知道 Elixir 不会跟踪这些变量的状态,因此会出现这个问题,但必须有一个聪明的方法使用 mapreduce...?

谢谢

Enum.group_by 应该有帮助:

Repo.all(query) 
|> Enum.group_by(fn x -> x.release_id end, fn t -> t.track end)