mirror of
https://github.com/SoPat712/allstarr.git
synced 2026-02-10 16:08:39 -05:00
fix: check all permutations of title/artist/album in search scoring
This commit is contained in:
@@ -169,14 +169,14 @@ public class JellyfinController : ControllerBase
|
|||||||
var (localSongs, localAlbums, localArtists) = _modelMapper.ParseItemsResponse(jellyfinResult);
|
var (localSongs, localAlbums, localArtists) = _modelMapper.ParseItemsResponse(jellyfinResult);
|
||||||
|
|
||||||
// Score and filter Jellyfin results by relevance
|
// Score and filter Jellyfin results by relevance
|
||||||
var scoredLocalSongs = ScoreSearchResults(cleanQuery, localSongs, s => s.Title, s => s.Artist, isExternal: false);
|
var scoredLocalSongs = ScoreSearchResults(cleanQuery, localSongs, s => s.Title, s => s.Artist, s => s.Album, isExternal: false);
|
||||||
var scoredLocalAlbums = ScoreSearchResults(cleanQuery, localAlbums, a => a.Title, a => a.Artist, isExternal: false);
|
var scoredLocalAlbums = ScoreSearchResults(cleanQuery, localAlbums, a => a.Title, a => a.Artist, _ => null, isExternal: false);
|
||||||
var scoredLocalArtists = ScoreSearchResults(cleanQuery, localArtists, a => a.Name, _ => null, isExternal: false);
|
var scoredLocalArtists = ScoreSearchResults(cleanQuery, localArtists, a => a.Name, _ => null, _ => null, isExternal: false);
|
||||||
|
|
||||||
// Score external results with a small boost
|
// Score external results with a small boost
|
||||||
var scoredExternalSongs = ScoreSearchResults(cleanQuery, externalResult.Songs, s => s.Title, s => s.Artist, isExternal: true);
|
var scoredExternalSongs = ScoreSearchResults(cleanQuery, externalResult.Songs, s => s.Title, s => s.Artist, s => s.Album, isExternal: true);
|
||||||
var scoredExternalAlbums = ScoreSearchResults(cleanQuery, externalResult.Albums, a => a.Title, a => a.Artist, isExternal: true);
|
var scoredExternalAlbums = ScoreSearchResults(cleanQuery, externalResult.Albums, a => a.Title, a => a.Artist, _ => null, isExternal: true);
|
||||||
var scoredExternalArtists = ScoreSearchResults(cleanQuery, externalResult.Artists, a => a.Name, _ => null, isExternal: true);
|
var scoredExternalArtists = ScoreSearchResults(cleanQuery, externalResult.Artists, a => a.Name, _ => null, _ => null, isExternal: true);
|
||||||
|
|
||||||
// Merge and sort by score (no filtering - just reorder by relevance)
|
// Merge and sort by score (no filtering - just reorder by relevance)
|
||||||
var allSongs = scoredLocalSongs.Concat(scoredExternalSongs)
|
var allSongs = scoredLocalSongs.Concat(scoredExternalSongs)
|
||||||
@@ -1774,36 +1774,56 @@ public class JellyfinController : ControllerBase
|
|||||||
private static List<(T Item, int Score)> ScoreSearchResults<T>(
|
private static List<(T Item, int Score)> ScoreSearchResults<T>(
|
||||||
string query,
|
string query,
|
||||||
List<T> items,
|
List<T> items,
|
||||||
Func<T, string> primaryField,
|
Func<T, string> titleField,
|
||||||
Func<T, string?> secondaryField,
|
Func<T, string?> artistField,
|
||||||
|
Func<T, string?> albumField,
|
||||||
bool isExternal = false)
|
bool isExternal = false)
|
||||||
{
|
{
|
||||||
return items.Select(item =>
|
return items.Select(item =>
|
||||||
{
|
{
|
||||||
var primary = primaryField(item) ?? "";
|
var title = titleField(item) ?? "";
|
||||||
var secondary = secondaryField(item) ?? "";
|
var artist = artistField(item) ?? "";
|
||||||
|
var album = albumField(item) ?? "";
|
||||||
|
|
||||||
// Score against primary field (title/name)
|
var scores = new List<int>();
|
||||||
var primaryScore = FuzzyMatcher.CalculateSimilarity(query, primary);
|
|
||||||
|
|
||||||
// Score against secondary field (artist) if provided
|
// Individual field scores
|
||||||
var secondaryScore = string.IsNullOrEmpty(secondary)
|
scores.Add(FuzzyMatcher.CalculateSimilarity(query, title));
|
||||||
? 0
|
if (!string.IsNullOrEmpty(artist))
|
||||||
: FuzzyMatcher.CalculateSimilarity(query, secondary);
|
scores.Add(FuzzyMatcher.CalculateSimilarity(query, artist));
|
||||||
|
if (!string.IsNullOrEmpty(album))
|
||||||
|
scores.Add(FuzzyMatcher.CalculateSimilarity(query, album));
|
||||||
|
|
||||||
// Score against combined "title artist" and "artist title" for queries like "say why zach bryan"
|
// Two-field combinations
|
||||||
var combinedScore = 0;
|
if (!string.IsNullOrEmpty(artist))
|
||||||
if (!string.IsNullOrEmpty(secondary))
|
|
||||||
{
|
{
|
||||||
var combined1 = $"{primary} {secondary}";
|
scores.Add(FuzzyMatcher.CalculateSimilarity(query, $"{title} {artist}"));
|
||||||
var combined2 = $"{secondary} {primary}";
|
scores.Add(FuzzyMatcher.CalculateSimilarity(query, $"{artist} {title}"));
|
||||||
var score1 = FuzzyMatcher.CalculateSimilarity(query, combined1);
|
}
|
||||||
var score2 = FuzzyMatcher.CalculateSimilarity(query, combined2);
|
if (!string.IsNullOrEmpty(album))
|
||||||
combinedScore = Math.Max(score1, score2);
|
{
|
||||||
|
scores.Add(FuzzyMatcher.CalculateSimilarity(query, $"{title} {album}"));
|
||||||
|
scores.Add(FuzzyMatcher.CalculateSimilarity(query, $"{album} {title}"));
|
||||||
|
}
|
||||||
|
if (!string.IsNullOrEmpty(artist) && !string.IsNullOrEmpty(album))
|
||||||
|
{
|
||||||
|
scores.Add(FuzzyMatcher.CalculateSimilarity(query, $"{artist} {album}"));
|
||||||
|
scores.Add(FuzzyMatcher.CalculateSimilarity(query, $"{album} {artist}"));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Three-field combinations (all permutations)
|
||||||
|
if (!string.IsNullOrEmpty(artist) && !string.IsNullOrEmpty(album))
|
||||||
|
{
|
||||||
|
scores.Add(FuzzyMatcher.CalculateSimilarity(query, $"{title} {artist} {album}"));
|
||||||
|
scores.Add(FuzzyMatcher.CalculateSimilarity(query, $"{title} {album} {artist}"));
|
||||||
|
scores.Add(FuzzyMatcher.CalculateSimilarity(query, $"{artist} {title} {album}"));
|
||||||
|
scores.Add(FuzzyMatcher.CalculateSimilarity(query, $"{artist} {album} {title}"));
|
||||||
|
scores.Add(FuzzyMatcher.CalculateSimilarity(query, $"{album} {title} {artist}"));
|
||||||
|
scores.Add(FuzzyMatcher.CalculateSimilarity(query, $"{album} {artist} {title}"));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Use the best score from all attempts
|
// Use the best score from all attempts
|
||||||
var baseScore = Math.Max(Math.Max(primaryScore, secondaryScore), combinedScore);
|
var baseScore = scores.Max();
|
||||||
|
|
||||||
// Give external results a small boost (+5 points) to prioritize the larger catalog
|
// Give external results a small boost (+5 points) to prioritize the larger catalog
|
||||||
var finalScore = isExternal ? Math.Min(100, baseScore + 5) : baseScore;
|
var finalScore = isExternal ? Math.Min(100, baseScore + 5) : baseScore;
|
||||||
|
|||||||
Reference in New Issue
Block a user