improve result ranking

This commit is contained in:
Drew Weymouth
2023-11-05 15:05:05 -08:00
parent de8539df0a
commit fd9ae477b6
+19 -10
View File
@@ -35,7 +35,8 @@ func (s *subsonicMediaProvider) SearchAll(searchQuery string, maxResults int) ([
wg.Done() wg.Done()
}() }()
queryLowerWords := strings.Fields(strings.ToLower(sanitize.Accents(searchQuery))) querySanitized := strings.ToLower(sanitize.Accents(searchQuery))
queryLowerWords := strings.Fields(querySanitized)
wg.Add(1) wg.Add(1)
go func() { go func() {
@@ -65,7 +66,7 @@ func (s *subsonicMediaProvider) SearchAll(searchQuery string, maxResults int) ([
} }
results := mergeResults(result, playlists, genres) results := mergeResults(result, playlists, genres)
rankResults(results, queryLowerWords) rankResults(results, querySanitized, queryLowerWords)
if len(results) > maxResults { if len(results) > maxResults {
results = results[:maxResults] results = results[:maxResults]
} }
@@ -143,27 +144,35 @@ func mergeResults(
return results return results
} }
func rankResults(results []*mediaprovider.SearchResult, queryTerms []string) { func rankResults(results []*mediaprovider.SearchResult, fullQuery string, queryTerms []string) {
if len(queryTerms) == 0 || len(results) < 2 { if len(queryTerms) == 0 || len(results) < 2 {
return return
} }
sanitizeMemo := make([]string, len(results)) sanitizeMemo := make(map[string]string, len(results))
sanitized := func(s string, i int) string { sanitized := func(s string) string {
if x := sanitizeMemo[i]; x != "" { if x, ok := sanitizeMemo[s]; ok {
return x return x
} }
x := strings.ToLower(sanitize.Accents(s)) x := strings.ToLower(sanitize.Accents(s))
sanitizeMemo[i] = x sanitizeMemo[s] = x
return x return x
} }
sort.Slice(results, func(i, j int) bool { sort.Slice(results, func(i, j int) bool {
// Compare by search query terms
a, b := results[i], results[j] a, b := results[i], results[j]
aName := sanitized(a.Name, i) aName := sanitized(a.Name)
bName := sanitized(b.Name, j) bName := sanitized(b.Name)
// Compare by entire query
matchesA, matchesB := strings.Contains(aName, fullQuery), strings.Contains(bName, fullQuery)
if matchesA && !matchesB {
return true // item A has a direct match with the full query and B does not
} else if matchesB && !matchesA {
return false // item B matches but not A
}
// Compare by search query terms
for _, term := range queryTerms { for _, term := range queryTerms {
firstTermIdxA, firstTermIdxB := strings.Index(aName, term), strings.Index(bName, term) firstTermIdxA, firstTermIdxB := strings.Index(aName, term), strings.Index(bName, term)
if firstTermIdxA >= 0 && firstTermIdxB < 0 { if firstTermIdxA >= 0 && firstTermIdxB < 0 {