feat: fuzzy search with parallel DB/MusicBrainz execution
- Add pg_trgm fuzzy search to PostgreSQL artist repository - Add Lucene fuzzy query (~0.7) for MusicBrainz artist search - Run DB and MusicBrainz searches in parallel goroutines - Cache MusicBrainz results to DB for accumulation - Deduplicate results by external ID - Filter out special purpose artists (type=Other) - Add SaveAll method for batch artist inserts - Move database schema to containers repo
This commit is contained in:
@@ -42,8 +42,8 @@ func (p *Provider) SearchArtists(ctx context.Context, query string, limit, offse
|
||||
limit = 25
|
||||
}
|
||||
|
||||
escapedQuery := escapeQuery(query)
|
||||
data, err := p.client.search(ctx, "artist", fmt.Sprintf("artist:%s", escapedQuery), limit, offset)
|
||||
luceneQuery := buildFuzzyArtistQuery(query, 0.7)
|
||||
data, err := p.client.search(ctx, "artist", luceneQuery, limit, offset)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("search artists: %w", err)
|
||||
}
|
||||
@@ -311,6 +311,31 @@ func selectCanonicalRelease(releases []*mbRelease) *mbRelease {
|
||||
return best
|
||||
}
|
||||
|
||||
func buildFuzzyArtistQuery(query string, similarity float64) string {
|
||||
terms := strings.Fields(query)
|
||||
if len(terms) == 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
var parts []string
|
||||
for _, term := range terms {
|
||||
escaped := escapeForFuzzy(term)
|
||||
parts = append(parts, fmt.Sprintf("%s~%.1f", escaped, similarity))
|
||||
}
|
||||
|
||||
termQuery := strings.Join(parts, " AND ")
|
||||
return fmt.Sprintf("(artist:(%s) OR alias:(%s))", termQuery, termQuery)
|
||||
}
|
||||
|
||||
func escapeForFuzzy(s string) string {
|
||||
special := []string{`+`, `-`, `&`, `|`, `!`, `(`, `)`, `{`, `}`, `[`, `]`, `^`, `"`, `:`, `/`, `\`}
|
||||
result := s
|
||||
for _, char := range special {
|
||||
result = strings.ReplaceAll(result, char, `\`+char)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func escapeQuery(s string) string {
|
||||
special := []string{`+`, `-`, `&`, `|`, `!`, `(`, `)`, `{`, `}`, `[`, `]`, `^`, `"`, `~`, `*`, `?`, `:`, `/`, `\`}
|
||||
result := s
|
||||
|
||||
Reference in New Issue
Block a user