diff --git a/model/album.go b/model/album.go index 8b67d6727..94b5ff9f7 100644 --- a/model/album.go +++ b/model/album.go @@ -52,6 +52,7 @@ type AlbumRepository interface { Put(*Album) error Get(id string) (*Album, error) GetAll(...QueryOptions) (Albums, error) + GetAllWithoutGenres(...QueryOptions) (Albums, error) Search(q string, offset int, size int) (Albums, error) Refresh(ids ...string) error AnnotatedRepository diff --git a/persistence/album_repository.go b/persistence/album_repository.go index 124a4995f..61c54c592 100644 --- a/persistence/album_repository.go +++ b/persistence/album_repository.go @@ -93,7 +93,18 @@ func (r *albumRepository) Exists(id string) (bool, error) { func (r *albumRepository) selectAlbum(options ...model.QueryOptions) SelectBuilder { sql := r.newSelectWithAnnotation("album.id", options...).Columns("album.*") - return r.withGenres(sql).GroupBy("album.id") + if len(options) > 0 && options[0].Filters != nil { + s, _, _ := options[0].Filters.ToSql() + // If there's any reference of genre in the filter, joins with genre + if strings.Contains(s, "genre") { + sql = r.withGenres(sql) + // If there's no filter on genre_id, group the results by media_file.id + if !strings.Contains(s, "genre_id") { + sql = sql.GroupBy("album.id") + } + } + } + return sql } func (r *albumRepository) Get(id string) (*model.Album, error) { @@ -118,13 +129,21 @@ func (r *albumRepository) Put(m *model.Album) error { } func (r *albumRepository) GetAll(options ...model.QueryOptions) (model.Albums, error) { + res, err := r.GetAllWithoutGenres(options...) + if err != nil { + return nil, err + } + err = r.loadAlbumGenres(&res) + return res, err +} + +func (r *albumRepository) GetAllWithoutGenres(options ...model.QueryOptions) (model.Albums, error) { sq := r.selectAlbum(options...) res := model.Albums{} err := r.queryAll(sq, &res) if err != nil { return nil, err } - err = r.loadAlbumGenres(&res) return res, err } diff --git a/persistence/sql_genres.go b/persistence/sql_genres.go index ce05a6e54..397e43368 100644 --- a/persistence/sql_genres.go +++ b/persistence/sql_genres.go @@ -45,7 +45,7 @@ func (r *sqlRepository) loadMediaFileGenres(mfs *model.MediaFiles) error { m[mf.ID] = mf } - return utils.RangeByChunks(ids, 100, func(ids []string) error { + return utils.RangeByChunks(ids, 900, func(ids []string) error { sql := Select("g.*", "mg.media_file_id").From("genre g").Join("media_file_genres mg on mg.genre_id = g.id"). Where(Eq{"mg.media_file_id": ids}).OrderBy("mg.media_file_id", "mg.rowid") var genres []struct { @@ -74,7 +74,7 @@ func (r *sqlRepository) loadAlbumGenres(mfs *model.Albums) error { m[mf.ID] = mf } - return utils.RangeByChunks(ids, 100, func(ids []string) error { + return utils.RangeByChunks(ids, 900, func(ids []string) error { sql := Select("g.*", "ag.album_id").From("genre g").Join("album_genres ag on ag.genre_id = g.id"). Where(Eq{"ag.album_id": ids}).OrderBy("ag.album_id", "ag.rowid") var genres []struct { @@ -103,7 +103,7 @@ func (r *sqlRepository) loadArtistGenres(mfs *model.Artists) error { m[mf.ID] = mf } - return utils.RangeByChunks(ids, 100, func(ids []string) error { + return utils.RangeByChunks(ids, 900, func(ids []string) error { sql := Select("g.*", "ag.artist_id").From("genre g").Join("artist_genres ag on ag.genre_id = g.id"). Where(Eq{"ag.artist_id": ids}).OrderBy("ag.artist_id", "ag.rowid") var genres []struct { diff --git a/server/subsonic/album_lists.go b/server/subsonic/album_lists.go index 3ca8bb44d..bcd0b40b7 100644 --- a/server/subsonic/album_lists.go +++ b/server/subsonic/album_lists.go @@ -63,7 +63,7 @@ func (c *AlbumListController) getAlbumList(r *http.Request) (model.Albums, int64 opts.Offset = utils.ParamInt(r, "offset", 0) opts.Max = utils.MinInt(utils.ParamInt(r, "size", 10), 500) - albums, err := c.ds.Album(r.Context()).GetAll(opts) + albums, err := c.ds.Album(r.Context()).GetAllWithoutGenres(opts) if err != nil { log.Error(r, "Error retrieving albums", "error", err) @@ -113,7 +113,7 @@ func (c *AlbumListController) GetStarred(w http.ResponseWriter, r *http.Request) log.Error(r, "Error retrieving starred artists", "error", err) return nil, err } - albums, err := c.ds.Album(ctx).GetAll(options) + albums, err := c.ds.Album(ctx).GetAllWithoutGenres(options) if err != nil { log.Error(r, "Error retrieving starred albums", "error", err) return nil, err diff --git a/server/subsonic/browsing.go b/server/subsonic/browsing.go index 2f65aee1c..7caa959f5 100644 --- a/server/subsonic/browsing.go +++ b/server/subsonic/browsing.go @@ -149,7 +149,7 @@ func (c *BrowsingController) GetArtist(w http.ResponseWriter, r *http.Request) ( return nil, err } - albums, err := c.ds.Album(ctx).GetAll(filter.AlbumsByArtistID(id)) + albums, err := c.ds.Album(ctx).GetAllWithoutGenres(filter.AlbumsByArtistID(id)) if err != nil { log.Error(ctx, "Error retrieving albums by artist", "id", id, "name", artist.Name, err) return nil, err @@ -337,7 +337,7 @@ func (c *BrowsingController) buildArtistDirectory(ctx context.Context, artist *m dir.Starred = &artist.StarredAt } - albums, err := c.ds.Album(ctx).GetAll(filter.AlbumsByArtistID(artist.ID)) + albums, err := c.ds.Album(ctx).GetAllWithoutGenres(filter.AlbumsByArtistID(artist.ID)) if err != nil { return nil, err } diff --git a/tests/mock_album_repo.go b/tests/mock_album_repo.go index 40fdfd2ed..65ddfecdb 100644 --- a/tests/mock_album_repo.go +++ b/tests/mock_album_repo.go @@ -74,6 +74,10 @@ func (m *MockAlbumRepo) GetAll(qo ...model.QueryOptions) (model.Albums, error) { return m.all, nil } +func (m *MockAlbumRepo) GetAllWithoutGenres(qo ...model.QueryOptions) (model.Albums, error) { + return m.GetAll(qo...) +} + func (m *MockAlbumRepo) IncPlayCount(id string, timestamp time.Time) error { if m.err { return errors.New("error")