quintodrome/engine/search.go

159 lines
4 KiB
Go
Raw Normal View History

package engine
import (
"strings"
"github.com/astaxie/beego"
"github.com/deluan/gomate"
"github.com/deluan/gosonic/domain"
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
SearchArtist(q string, offset int, size int) (Entries, error)
SearchAlbum(q string, offset int, size int) (Entries, error)
SearchSong(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...)
}
2016-03-21 19:11:57 -08:00
func (s *search) SearchArtist(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)
if criticalError("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
}
2016-03-21 19:11:57 -08:00
func (s *search) SearchAlbum(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)
if criticalError("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
2016-03-21 19:11:57 -08:00
func (s *search) SearchSong(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)
if criticalError("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
}
func criticalError(kind, id string, err error) bool {
switch {
case err != nil:
return true
case err == domain.ErrNotFound:
beego.Warn(kind, "Id", id, "not in the DB. Need a reindex?")
}
return false
}