Return matching_records list from top_albums_attach_metadata
Apply the same release-group JSON aggregation pattern to top albums queries. Add JSON parsing in get_top_albums/1 and get_top_albums_by_days/2.
This commit is contained in:
@@ -282,6 +282,7 @@ defmodule MusicLibrary.ListeningStats do
|
|||||||
|> top_albums_aggregate_query(limit)
|
|> top_albums_aggregate_query(limit)
|
||||||
|> top_albums_attach_metadata()
|
|> top_albums_attach_metadata()
|
||||||
|> Repo.all()
|
|> Repo.all()
|
||||||
|
|> parse_top_albums_matching_records()
|
||||||
end
|
end
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
@@ -299,6 +300,7 @@ defmodule MusicLibrary.ListeningStats do
|
|||||||
|> top_albums_aggregate_query(limit)
|
|> top_albums_aggregate_query(limit)
|
||||||
|> top_albums_attach_metadata()
|
|> top_albums_attach_metadata()
|
||||||
|> Repo.all()
|
|> Repo.all()
|
||||||
|
|> parse_top_albums_matching_records()
|
||||||
end
|
end
|
||||||
|
|
||||||
@doc """
|
@doc """
|
||||||
@@ -437,10 +439,11 @@ defmodule MusicLibrary.ListeningStats do
|
|||||||
limit: ^limit
|
limit: ^limit
|
||||||
end
|
end
|
||||||
|
|
||||||
# Attaches `record_releases` and `cover_hash` lookups to the LIMIT'd
|
# Attaches `matching_records` and `cover_hash` lookups to the LIMIT'd
|
||||||
# aggregate result via correlated scalar subqueries. The cost of these
|
# aggregate result via correlated subqueries. Groups by release group
|
||||||
# lookups scales with the number of result rows (≤ limit), not with the
|
# (records.musicbrainz_id) so all records for the same album appear.
|
||||||
# size of `record_releases`.
|
# The cost scales with the number of result rows (≤ limit), not with
|
||||||
|
# the size of `record_releases`.
|
||||||
defp top_albums_attach_metadata(aggregate_query) do
|
defp top_albums_attach_metadata(aggregate_query) do
|
||||||
from g in subquery(aggregate_query),
|
from g in subquery(aggregate_query),
|
||||||
select: %{
|
select: %{
|
||||||
@@ -450,20 +453,40 @@ defmodule MusicLibrary.ListeningStats do
|
|||||||
play_count: g.play_count,
|
play_count: g.play_count,
|
||||||
cover_url: g.cover_url,
|
cover_url: g.cover_url,
|
||||||
album_musicbrainz_id: g.album_musicbrainz_id,
|
album_musicbrainz_id: g.album_musicbrainz_id,
|
||||||
collected_record_id:
|
matching_records:
|
||||||
fragment(
|
fragment(
|
||||||
"(SELECT min(record_id) FROM record_releases WHERE release_id = ? AND purchased_at IS NOT NULL)",
|
"""
|
||||||
g.album_musicbrainz_id
|
(SELECT json_group_array(json_object(\
|
||||||
),
|
'id', r.id, \
|
||||||
wishlisted_record_id:
|
'title', r.title, \
|
||||||
fragment(
|
'format', r.format, \
|
||||||
"(SELECT min(record_id) FROM record_releases WHERE release_id = ? AND purchased_at IS NULL)",
|
'type', r.type, \
|
||||||
|
'purchased_at', r.purchased_at, \
|
||||||
|
'cover_hash', r.cover_hash\
|
||||||
|
)) \
|
||||||
|
FROM records r \
|
||||||
|
WHERE r.musicbrainz_id = (\
|
||||||
|
SELECT r2.musicbrainz_id FROM records r2 \
|
||||||
|
INNER JOIN record_releases rr ON rr.record_id = r2.id \
|
||||||
|
WHERE rr.release_id = ? \
|
||||||
|
LIMIT 1\
|
||||||
|
))\
|
||||||
|
""",
|
||||||
g.album_musicbrainz_id
|
g.album_musicbrainz_id
|
||||||
),
|
),
|
||||||
cover_hash:
|
cover_hash:
|
||||||
fragment(
|
fragment(
|
||||||
"coalesce((SELECT min(cover_hash) FROM record_releases WHERE release_id = ? AND purchased_at IS NOT NULL), (SELECT min(cover_hash) FROM record_releases WHERE release_id = ? AND purchased_at IS NULL))",
|
"""
|
||||||
g.album_musicbrainz_id,
|
(SELECT r.cover_hash FROM records r \
|
||||||
|
WHERE r.musicbrainz_id = (\
|
||||||
|
SELECT r2.musicbrainz_id FROM records r2 \
|
||||||
|
INNER JOIN record_releases rr ON rr.record_id = r2.id \
|
||||||
|
WHERE rr.release_id = ? \
|
||||||
|
LIMIT 1\
|
||||||
|
) \
|
||||||
|
ORDER BY (CASE WHEN r.purchased_at IS NOT NULL THEN 0 ELSE 1 END), r.id \
|
||||||
|
LIMIT 1)\
|
||||||
|
""",
|
||||||
g.album_musicbrainz_id
|
g.album_musicbrainz_id
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -571,6 +594,12 @@ defmodule MusicLibrary.ListeningStats do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
defp parse_top_albums_matching_records(albums) do
|
||||||
|
Enum.map(albums, fn album ->
|
||||||
|
%{album | matching_records: parse_matching_records(album.matching_records)}
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
|
||||||
defp parse_matching_records(nil), do: []
|
defp parse_matching_records(nil), do: []
|
||||||
defp parse_matching_records("[]"), do: []
|
defp parse_matching_records("[]"), do: []
|
||||||
|
|
||||||
|
|||||||
@@ -417,7 +417,6 @@ defmodule MusicLibrary.ListeningStatsTest do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@tag :skip
|
|
||||||
test "get_top_albums returns one entry per album", %{expected_record_id: expected_record_id} do
|
test "get_top_albums returns one entry per album", %{expected_record_id: expected_record_id} do
|
||||||
results = ListeningStats.get_top_albums(limit: 10)
|
results = ListeningStats.get_top_albums(limit: 10)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user