从 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 不会跟踪这些变量的状态,因此会出现这个问题,但必须有一个聪明的方法使用 map
或 reduce
...?
谢谢
Enum.group_by
应该有帮助:
Repo.all(query)
|> Enum.group_by(fn x -> x.release_id end, fn t -> t.track end)
我从 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 不会跟踪这些变量的状态,因此会出现这个问题,但必须有一个聪明的方法使用 map
或 reduce
...?
谢谢
Enum.group_by
应该有帮助:
Repo.all(query)
|> Enum.group_by(fn x -> x.release_id end, fn t -> t.track end)