fix(db): split seed_info CTE so similar-artist works without seed genre

The combined seed_info CTE filtered the seed out when its genre was
NULL/empty. Restored the spec's two-CTE design (seed_artist + seed_tags)
so similar-artist matching works regardless of the seed's genre coverage.
Drops the genre workaround from the SimilarArtist test.
This commit is contained in:
2026-04-29 08:43:42 -04:00
parent 51811c9d35
commit b8e3019654
3 changed files with 22 additions and 19 deletions
+11 -7
View File
@@ -36,9 +36,13 @@ WHERE t.id <> $2
-- Returns same shape as LoadRadioCandidates plus similarity_score column.
WITH
seed_info AS (
SELECT t.artist_id,
trim(g)::text AS tag
seed_artist AS (
SELECT artist_id
FROM tracks
WHERE tracks.id = $2
),
seed_tags AS (
SELECT trim(g) AS tag
FROM tracks t
LEFT JOIN LATERAL regexp_split_to_table(coalesce(t.genre, ''), '[;,]') AS g(tag) ON true
WHERE t.id = $2 AND trim(g) <> ''
@@ -63,7 +67,7 @@ similar_artists AS (
SELECT t.id AS track_id, asim.score * 0.5 AS sim_score
FROM artist_similarity asim
JOIN tracks t ON t.artist_id = asim.artist_b_id
JOIN (SELECT DISTINCT artist_id FROM seed_info) sa ON asim.artist_a_id = sa.artist_id
JOIN seed_artist sa ON asim.artist_a_id = sa.artist_id
WHERE asim.source = 'listenbrainz'
AND t.id NOT IN (SELECT id FROM excluded_ids)
ORDER BY asim.score DESC, random()
@@ -72,10 +76,10 @@ similar_artists AS (
tag_overlap AS (
SELECT t.id AS track_id,
(count(DISTINCT trim(g))::float8
/ GREATEST((SELECT count(DISTINCT tag) FROM seed_info), 1)) AS sim_score
/ GREATEST((SELECT count(*) FROM seed_tags), 1)) AS sim_score
FROM tracks t
LEFT JOIN LATERAL regexp_split_to_table(coalesce(t.genre, ''), '[;,]') AS g_split(g) ON true
WHERE trim(g_split.g) IN (SELECT tag FROM seed_info)
WHERE trim(g_split.g) IN (SELECT tag FROM seed_tags)
AND t.id NOT IN (SELECT id FROM excluded_ids)
AND t.id <> $2
GROUP BY t.id
@@ -92,7 +96,7 @@ likes_overlap AS (
SELECT 1 FROM tracks t
LEFT JOIN LATERAL regexp_split_to_table(coalesce(t.genre, ''), '[;,]') AS g_overlap(g) ON true
WHERE t.id = gl.track_id
AND trim(g_overlap.g) IN (SELECT tag FROM seed_info)
AND trim(g_overlap.g) IN (SELECT tag FROM seed_tags)
)
ORDER BY random()
LIMIT $8