From fc2a50e853ae233de9a8560021e8f08cd38dbe4c Mon Sep 17 00:00:00 2001 From: Caleb Allen Date: Mon, 30 Mar 2026 03:06:09 -0400 Subject: [PATCH] fix: revert to minBlendedScore=25, add separate zero-popularity filter MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit minBlendedScore=50 was too aggressive on the fast path where non-indexed MB results get zero popularity (blended score ~35). This killed all MB results that weren't in the explore index, leaving only library/index artists. New approach: two-tier filtering in filterAndCap: 1. minBlendedScore=25 — baseline filter for all artists 2. minZeroPopScore=50 — stricter filter for artists with NO LB popularity data (HasPopularity=false) HasPopularity is set by both reranking paths when an artist has any listen count in the index or LB API. Shannon Hale (zero listens, score 37) gets filtered by the zero-pop threshold. Regular MB results that happen to not be in the index but do have LB popularity pass the normal threshold. --- backend/explore/explore.go | 42 +++++++++++++++++++++++++++++++------- backend/explore/types.go | 1 + 2 files changed, 36 insertions(+), 7 deletions(-) diff --git a/backend/explore/explore.go b/backend/explore/explore.go index bb5bf80..75c374d 100644 --- a/backend/explore/explore.go +++ b/backend/explore/explore.go @@ -827,14 +827,28 @@ func scalePopularity(listens int) int { // filterAndCap removes low-scoring results, special-purpose // MusicBrainz artists, and limits each entity slice to maxResults. func filterAndCap(result *MBSearchResult) { - // Filter artists by minimum blended score and remove SPAs. + // Filter artists: remove SPAs and zero-popularity artists + // that aren't exact name matches. if len(result.Artists) > 0 { filtered := result.Artists[:0] for _, a := range result.Artists { - if a.Score >= minBlendedScore && !mbSpecialPurposeArtists[a.MBID] { - filtered = append(filtered, a) + if mbSpecialPurposeArtists[a.MBID] { + continue } + + if a.Score < minBlendedScore { + continue + } + + // Keep artists with popularity data. Also keep artists + // without popularity if they have a high enough score + // (likely exact or close name matches). + if !a.HasPopularity && a.Score < minZeroPopScore { + continue + } + + filtered = append(filtered, a) } result.Artists = filtered @@ -899,9 +913,13 @@ const ( // minBlendedScore is the floor for artists and recordings // after popularity reranking and tier adjustment (0–100 scale). - // At 50, artists with zero LB popularity and partial name - // matches are filtered out. - minBlendedScore = 50 + minBlendedScore = 25 + + // minZeroPopScore is the floor for artists with zero LB + // popularity data. Higher than minBlendedScore so that + // obscure artists without any listening history are filtered + // unless they're a very strong name match (exact or near-exact). + minZeroPopScore = 50 ) // tierBonus maps artist name-match tiers to percentage score multipliers. @@ -984,9 +1002,10 @@ func (e *Service) boostWithIndexPopularity(result *MBSearchResult) { // Build per-entity maps from the batch result. artistPop := make(map[string]int, len(result.Artists)) - for _, a := range result.Artists { + for i, a := range result.Artists { if pop, ok := popMap[a.MBID]; ok { artistPop[a.MBID] = pop + result.Artists[i].HasPopularity = true } } @@ -1095,6 +1114,15 @@ func (e *Service) boostWithPopularity(result *MBSearchResult) { } } + // Mark artists that have popularity data. + if artistPop != nil { + for i := range result.Artists { + if _, ok := artistPop[result.Artists[i].MBID]; ok { + result.Artists[i].HasPopularity = true + } + } + } + // Rerank each entity type. rerankArtists(result.Artists, artistPop) rerankRecordings(result.Recordings, recordingPop) diff --git a/backend/explore/types.go b/backend/explore/types.go index 5b13a00..a49028f 100644 --- a/backend/explore/types.go +++ b/backend/explore/types.go @@ -26,6 +26,7 @@ type MBArtist struct { Disambiguation string `json:"disambiguation"` Score int `json:"score"` OriginalScore int `json:"-"` // MB search relevance, preserved across reranking + HasPopularity bool `json:"-"` // true if LB/index had listen data for this artist } // MBReleaseGroup is a Wails-friendly projection of a MusicBrainz