【问题标题】:Map from Ecto query into Keyword List从 Ecto 查询映射到关键字列表
【发布时间】:2021-07-27 19:42:18
【问题描述】:

我是从 Ruby on Rails 世界进入 Elixir 的。

我有下表:

 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{} 结果。

本质上是看表的关键字对:

%{ release_side_id =&gt; [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...?

谢谢

【问题讨论】:

标签: elixir phoenix-framework ecto


【解决方案1】:

Enum.group_by 应该有帮助:

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

【讨论】:

  • 太棒了,是的,谢谢。在阅读您的答案之前,我刚刚尝试过Enum.group_by(fn x -&gt; x.release_side_id end),它也有效。订单也保留了!谢谢!
猜你喜欢
  • 1970-01-01
  • 2021-03-24
  • 2017-10-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-02-21
  • 2022-12-14
  • 1970-01-01
相关资源
最近更新 更多