quintodrome/engine/search.go

160 lines
4.2 KiB
Go
Raw Normal View History

package engine
import (
2020-01-08 16:45:07 -09:00
"context"
"strings"
2017-04-01 05:47:14 -08:00
"github.com/cloudsonic/sonic-server/domain"
2020-01-08 16:45:07 -09:00
"github.com/cloudsonic/sonic-server/log"
"github.com/deluan/gomate"
2016-03-15 12:23:39 -08:00
"github.com/kennygrant/sanitize"
)
type Search interface {
2016-03-10 19:24:30 -09:00
ClearAll() error
IndexArtist(ar *domain.Artist) error
2016-03-10 19:24:30 -09:00
IndexAlbum(al *domain.Album) error
IndexMediaFile(mf *domain.MediaFile) error
2016-03-10 20:37:07 -09:00
2016-03-26 18:34:20 -08:00
RemoveArtist(ids ...string) error
RemoveAlbum(ids ...string) error
RemoveMediaFile(ids ...string) error
2020-01-08 16:45:07 -09:00
SearchArtist(ctx context.Context, q string, offset int, size int) (Entries, error)
SearchAlbum(ctx context.Context, q string, offset int, size int) (Entries, error)
SearchSong(ctx context.Context, q string, offset int, size int) (Entries, error)
}
type search struct {
artistRepo domain.ArtistRepository
albumRepo domain.AlbumRepository
mfileRepo domain.MediaFileRepository
2016-03-10 20:37:07 -09:00
idxArtist gomate.Indexer
idxAlbum gomate.Indexer
idxSong gomate.Indexer
sArtist gomate.Searcher
sAlbum gomate.Searcher
sSong gomate.Searcher
}
2016-03-10 20:37:07 -09:00
func NewSearch(ar domain.ArtistRepository, alr domain.AlbumRepository, mr domain.MediaFileRepository, db gomate.DB) Search {
2016-03-21 19:11:57 -08:00
s := &search{artistRepo: ar, albumRepo: alr, mfileRepo: mr}
2016-03-10 20:37:07 -09:00
s.idxArtist = gomate.NewIndexer(db, "gomate-artist-idx")
s.sArtist = gomate.NewSearcher(db, "gomate-artist-idx")
s.idxAlbum = gomate.NewIndexer(db, "gomate-album-idx")
s.sAlbum = gomate.NewSearcher(db, "gomate-album-idx")
s.idxSong = gomate.NewIndexer(db, "gomate-song-idx")
s.sSong = gomate.NewSearcher(db, "gomate-song-idx")
return s
}
2016-03-21 19:11:57 -08:00
func (s *search) ClearAll() error {
2016-03-23 08:35:10 -08:00
if err := s.idxArtist.Clear(); err != nil {
return err
}
if err := s.idxAlbum.Clear(); err != nil {
return err
}
if err := s.idxSong.Clear(); err != nil {
return err
}
return nil
2016-03-10 19:24:30 -09:00
}
2016-03-21 19:11:57 -08:00
func (s *search) IndexArtist(ar *domain.Artist) error {
2016-03-15 12:23:39 -08:00
return s.idxArtist.Index(ar.Id, sanitize.Accents(strings.ToLower(ar.Name)))
2016-03-10 19:24:30 -09:00
}
2016-03-21 19:11:57 -08:00
func (s *search) IndexAlbum(al *domain.Album) error {
2016-03-15 12:23:39 -08:00
return s.idxAlbum.Index(al.Id, sanitize.Accents(strings.ToLower(al.Name)))
2016-03-10 19:24:30 -09:00
}
2016-03-21 19:11:57 -08:00
func (s *search) IndexMediaFile(mf *domain.MediaFile) error {
2016-03-15 12:23:39 -08:00
return s.idxSong.Index(mf.Id, sanitize.Accents(strings.ToLower(mf.Title)))
2016-03-10 20:37:07 -09:00
}
2016-03-26 18:34:20 -08:00
func (s *search) RemoveArtist(ids ...string) error {
return s.idxArtist.Remove(ids...)
}
2016-03-26 18:34:20 -08:00
func (s *search) RemoveAlbum(ids ...string) error {
return s.idxAlbum.Remove(ids...)
}
2016-03-26 18:34:20 -08:00
func (s *search) RemoveMediaFile(ids ...string) error {
return s.idxSong.Remove(ids...)
}
2020-01-08 16:45:07 -09:00
func (s *search) SearchArtist(ctx context.Context, q string, offset int, size int) (Entries, error) {
2016-03-15 12:23:39 -08:00
q = sanitize.Accents(strings.ToLower(strings.TrimSuffix(q, "*")))
2016-03-11 06:03:33 -09:00
min := offset
max := min + size - 1
resp, err := s.sArtist.Search(q, min, max)
2016-03-10 20:37:07 -09:00
if err != nil {
return nil, nil
}
res := make(Entries, 0, len(resp))
for _, id := range resp {
2016-03-10 20:37:07 -09:00
a, err := s.artistRepo.Get(id)
2020-01-08 16:45:07 -09:00
if criticalError(ctx, "Artist", id, err) {
2016-03-10 20:37:07 -09:00
return nil, err
}
if err == nil {
2016-03-28 06:01:43 -08:00
res = append(res, FromArtist(a))
}
2016-03-11 05:10:40 -09:00
}
return res, nil
2016-03-11 05:10:40 -09:00
}
2020-01-08 16:45:07 -09:00
func (s *search) SearchAlbum(ctx context.Context, q string, offset int, size int) (Entries, error) {
2016-03-15 12:23:39 -08:00
q = sanitize.Accents(strings.ToLower(strings.TrimSuffix(q, "*")))
2016-03-11 06:03:33 -09:00
min := offset
max := min + size - 1
resp, err := s.sAlbum.Search(q, min, max)
2016-03-11 05:10:40 -09:00
if err != nil {
return nil, nil
}
res := make(Entries, 0, len(resp))
for _, id := range resp {
2016-03-11 05:10:40 -09:00
al, err := s.albumRepo.Get(id)
2020-01-08 16:45:07 -09:00
if criticalError(ctx, "Album", id, err) {
2016-03-11 05:10:40 -09:00
return nil, err
}
if err == nil {
res = append(res, FromAlbum(al))
}
2016-03-10 20:37:07 -09:00
}
return res, nil
}
2016-03-10 20:37:07 -09:00
2020-01-08 16:45:07 -09:00
func (s *search) SearchSong(ctx context.Context, q string, offset int, size int) (Entries, error) {
2016-03-15 12:23:39 -08:00
q = sanitize.Accents(strings.ToLower(strings.TrimSuffix(q, "*")))
2016-03-11 06:03:33 -09:00
min := offset
max := min + size - 1
resp, err := s.sSong.Search(q, min, max)
2016-03-11 05:10:40 -09:00
if err != nil {
return nil, nil
}
res := make(Entries, 0, len(resp))
for _, id := range resp {
2016-03-11 05:10:40 -09:00
mf, err := s.mfileRepo.Get(id)
2020-01-08 16:45:07 -09:00
if criticalError(ctx, "Song", id, err) {
2016-03-11 05:10:40 -09:00
return nil, err
}
if err == nil {
res = append(res, FromMediaFile(mf))
}
2016-03-11 05:10:40 -09:00
}
return res, nil
2016-03-11 05:10:40 -09:00
}
2020-01-08 16:45:07 -09:00
func criticalError(ctx context.Context, kind, id string, err error) bool {
switch {
case err != nil:
return true
case err == domain.ErrNotFound:
2020-01-08 16:45:07 -09:00
log.Warn(ctx, kind+"Id not in DB. Need a reindex?", "id", id)
}
return false
}