mirror of
https://github.com/gabehf/Koito.git
synced 2026-03-07 13:38:15 -08:00
fix: improve matching with identically named albums (#126)
* fix: improve matching with identically named albums * fix: incorrect sql query
This commit is contained in:
parent
97cd378535
commit
e45099c71a
6 changed files with 113 additions and 17 deletions
|
|
@ -32,6 +32,19 @@ JOIN artist_releases ar ON r.id = ar.release_id
|
||||||
WHERE r.title = ANY ($1::TEXT[]) AND ar.artist_id = $2
|
WHERE r.title = ANY ($1::TEXT[]) AND ar.artist_id = $2
|
||||||
LIMIT 1;
|
LIMIT 1;
|
||||||
|
|
||||||
|
-- name: GetReleaseByArtistAndTitlesNoMbzID :one
|
||||||
|
SELECT r.*
|
||||||
|
FROM releases_with_title r
|
||||||
|
JOIN artist_releases ar ON r.id = ar.release_id
|
||||||
|
WHERE r.title = ANY ($1::TEXT[])
|
||||||
|
AND ar.artist_id = $2
|
||||||
|
AND EXISTS (
|
||||||
|
SELECT 1
|
||||||
|
FROM releases r2
|
||||||
|
WHERE r2.id = r.id
|
||||||
|
AND r2.musicbrainz_id IS NULL
|
||||||
|
);
|
||||||
|
|
||||||
-- name: GetTopReleasesFromArtist :many
|
-- name: GetTopReleasesFromArtist :many
|
||||||
SELECT
|
SELECT
|
||||||
r.*,
|
r.*,
|
||||||
|
|
|
||||||
|
|
@ -82,26 +82,19 @@ func createOrUpdateAlbumWithMbzReleaseID(ctx context.Context, d db.DB, opts Asso
|
||||||
titles := []string{release.Title, opts.ReleaseName}
|
titles := []string{release.Title, opts.ReleaseName}
|
||||||
utils.Unique(&titles)
|
utils.Unique(&titles)
|
||||||
|
|
||||||
l.Debug().Msgf("Searching for albums '%v' from artist id %d in DB", titles, opts.Artists[0].ID)
|
l.Debug().Msgf("Searching for albums '%v' from artist id %d and no associated MusicBrainz ID in DB", titles, opts.Artists[0].ID)
|
||||||
album, err = d.GetAlbum(ctx, db.GetAlbumOpts{
|
album, err = d.GetAlbumWithNoMbzIDByTitles(ctx, opts.Artists[0].ID, titles)
|
||||||
ArtistID: opts.Artists[0].ID,
|
|
||||||
Titles: titles,
|
|
||||||
})
|
|
||||||
if err == nil {
|
if err == nil {
|
||||||
l.Debug().Msgf("Found album %s, updating with MusicBrainz Release ID...", album.Title)
|
l.Debug().Msgf("Found album %s, updating with MusicBrainz Release ID...", album.Title)
|
||||||
if album.MbzID == nil {
|
err := d.UpdateAlbum(ctx, db.UpdateAlbumOpts{
|
||||||
err := d.UpdateAlbum(ctx, db.UpdateAlbumOpts{
|
ID: album.ID,
|
||||||
ID: album.ID,
|
MusicBrainzID: opts.ReleaseMbzID,
|
||||||
MusicBrainzID: opts.ReleaseMbzID,
|
})
|
||||||
})
|
if err != nil {
|
||||||
if err != nil {
|
l.Err(err).Msg("createOrUpdateAlbumWithMbzReleaseID: failed to update album with MusicBrainz Release ID")
|
||||||
l.Err(err).Msg("createOrUpdateAlbumWithMbzReleaseID: failed to update album with MusicBrainz Release ID")
|
return nil, fmt.Errorf("createOrUpdateAlbumWithMbzReleaseID: %w", err)
|
||||||
return nil, fmt.Errorf("createOrUpdateAlbumWithMbzReleaseID: %w", err)
|
|
||||||
}
|
|
||||||
l.Debug().Msgf("Updated album '%s' with MusicBrainz Release ID", album.Title)
|
|
||||||
} else {
|
|
||||||
l.Warn().Msgf("Attempted to update album %s with MusicBrainz ID, but an existing ID was already found", album.Title)
|
|
||||||
}
|
}
|
||||||
|
l.Debug().Msgf("Updated album '%s' with MusicBrainz Release ID", album.Title)
|
||||||
|
|
||||||
if opts.ReleaseGroupMbzID != uuid.Nil {
|
if opts.ReleaseGroupMbzID != uuid.Nil {
|
||||||
aliases, err := opts.Mbzc.GetReleaseTitles(ctx, opts.ReleaseGroupMbzID)
|
aliases, err := opts.Mbzc.GetReleaseTitles(ctx, opts.ReleaseGroupMbzID)
|
||||||
|
|
|
||||||
|
|
@ -297,6 +297,7 @@ func TestSubmitListen_DoNotOverwriteMbzIDs(t *testing.T) {
|
||||||
}
|
}
|
||||||
artistMbzID := uuid.MustParse("10000000-0000-0000-0000-000000000000")
|
artistMbzID := uuid.MustParse("10000000-0000-0000-0000-000000000000")
|
||||||
releaseMbzID := uuid.MustParse("01000000-0000-0000-0000-000000000000")
|
releaseMbzID := uuid.MustParse("01000000-0000-0000-0000-000000000000")
|
||||||
|
existingReleaseMbzID := uuid.MustParse("00000000-0000-0000-0000-000000000101")
|
||||||
trackMbzID := uuid.MustParse("00100000-0000-0000-0000-000000000000")
|
trackMbzID := uuid.MustParse("00100000-0000-0000-0000-000000000000")
|
||||||
opts := catalog.SubmitListenOpts{
|
opts := catalog.SubmitListenOpts{
|
||||||
MbzCaller: mbzc,
|
MbzCaller: mbzc,
|
||||||
|
|
@ -337,6 +338,11 @@ func TestSubmitListen_DoNotOverwriteMbzIDs(t *testing.T) {
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, 0, count, "duplicate release group created")
|
assert.Equal(t, 0, count, "duplicate release group created")
|
||||||
count, err = store.Count(ctx, `
|
count, err = store.Count(ctx, `
|
||||||
|
SELECT COUNT(*) FROM releases_with_title WHERE musicbrainz_id = $1
|
||||||
|
`, existingReleaseMbzID)
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Equal(t, 1, count, "existing release group should not be overwritten")
|
||||||
|
count, err = store.Count(ctx, `
|
||||||
SELECT COUNT(*) FROM artists_with_name WHERE musicbrainz_id = $1
|
SELECT COUNT(*) FROM artists_with_name WHERE musicbrainz_id = $1
|
||||||
`, artistMbzID)
|
`, artistMbzID)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ type DB interface {
|
||||||
|
|
||||||
GetArtist(ctx context.Context, opts GetArtistOpts) (*models.Artist, error)
|
GetArtist(ctx context.Context, opts GetArtistOpts) (*models.Artist, error)
|
||||||
GetAlbum(ctx context.Context, opts GetAlbumOpts) (*models.Album, error)
|
GetAlbum(ctx context.Context, opts GetAlbumOpts) (*models.Album, error)
|
||||||
|
GetAlbumWithNoMbzIDByTitles(ctx context.Context, artistId int32, titles []string) (*models.Album, error)
|
||||||
GetTrack(ctx context.Context, opts GetTrackOpts) (*models.Track, error)
|
GetTrack(ctx context.Context, opts GetTrackOpts) (*models.Track, error)
|
||||||
GetArtistsForAlbum(ctx context.Context, id int32) ([]*models.Artist, error)
|
GetArtistsForAlbum(ctx context.Context, id int32) ([]*models.Artist, error)
|
||||||
GetArtistsForTrack(ctx context.Context, id int32) ([]*models.Artist, error)
|
GetArtistsForTrack(ctx context.Context, id int32) ([]*models.Artist, error)
|
||||||
|
|
|
||||||
|
|
@ -110,6 +110,56 @@ func (d *Psql) GetAlbum(ctx context.Context, opts db.GetAlbumOpts) (*models.Albu
|
||||||
return ret, nil
|
return ret, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *Psql) GetAlbumWithNoMbzIDByTitles(ctx context.Context, artistId int32, titles []string) (*models.Album, error) {
|
||||||
|
l := logger.FromContext(ctx)
|
||||||
|
ret := new(models.Album)
|
||||||
|
|
||||||
|
if artistId != 0 && len(titles) > 0 {
|
||||||
|
l.Debug().Msgf("GetAlbumWithNoMbzIDByTitles: Fetching release group from DB with artist_id %d and titles %v and no associated MusicBrainz ID", artistId, titles)
|
||||||
|
row, err := d.q.GetReleaseByArtistAndTitlesNoMbzID(ctx, repository.GetReleaseByArtistAndTitlesNoMbzIDParams{
|
||||||
|
ArtistID: artistId,
|
||||||
|
Column1: titles,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("GetAlbum: %w", err)
|
||||||
|
}
|
||||||
|
ret.ID = row.ID
|
||||||
|
ret.MbzID = row.MusicBrainzID
|
||||||
|
ret.Title = row.Title
|
||||||
|
ret.Image = row.Image
|
||||||
|
ret.VariousArtists = row.VariousArtists
|
||||||
|
} else {
|
||||||
|
return nil, errors.New("GetAlbumWithNoMbzIDByTitles: insufficient information to get album")
|
||||||
|
}
|
||||||
|
count, err := d.q.CountListensFromRelease(ctx, repository.CountListensFromReleaseParams{
|
||||||
|
ListenedAt: time.Unix(0, 0),
|
||||||
|
ListenedAt_2: time.Now(),
|
||||||
|
ReleaseID: ret.ID,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("GetAlbumWithNoMbzIDByTitles: CountListensFromRelease: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
seconds, err := d.CountTimeListenedToItem(ctx, db.TimeListenedOpts{
|
||||||
|
Timeframe: db.Timeframe{Period: db.PeriodAllTime},
|
||||||
|
AlbumID: ret.ID,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("GetAlbumWithNoMbzIDByTitles: CountTimeListenedToItem: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
firstListen, err := d.q.GetFirstListenFromRelease(ctx, ret.ID)
|
||||||
|
if err != nil && !errors.Is(err, pgx.ErrNoRows) {
|
||||||
|
return nil, fmt.Errorf("GetAlbumWithNoMbzIDByTitles: GetFirstListenFromRelease: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
ret.ListenCount = count
|
||||||
|
ret.TimeListened = seconds
|
||||||
|
ret.FirstListen = firstListen.ListenedAt.Unix()
|
||||||
|
|
||||||
|
return ret, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (d *Psql) SaveAlbum(ctx context.Context, opts db.SaveAlbumOpts) (*models.Album, error) {
|
func (d *Psql) SaveAlbum(ctx context.Context, opts db.SaveAlbumOpts) (*models.Album, error) {
|
||||||
l := logger.FromContext(ctx)
|
l := logger.FromContext(ctx)
|
||||||
var insertMbzID *uuid.UUID
|
var insertMbzID *uuid.UUID
|
||||||
|
|
|
||||||
|
|
@ -195,6 +195,39 @@ func (q *Queries) GetReleaseByArtistAndTitles(ctx context.Context, arg GetReleas
|
||||||
return i, err
|
return i, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getReleaseByArtistAndTitlesNoMbzID = `-- name: GetReleaseByArtistAndTitlesNoMbzID :one
|
||||||
|
SELECT r.id, r.musicbrainz_id, r.image, r.various_artists, r.image_source, r.title
|
||||||
|
FROM releases_with_title r
|
||||||
|
JOIN artist_releases ar ON r.id = ar.release_id
|
||||||
|
WHERE r.title = ANY ($1::TEXT[])
|
||||||
|
AND ar.artist_id = $2
|
||||||
|
AND EXISTS (
|
||||||
|
SELECT 1
|
||||||
|
FROM releases r2
|
||||||
|
WHERE r2.id = r.id
|
||||||
|
AND r2.musicbrainz_id IS NULL
|
||||||
|
)
|
||||||
|
`
|
||||||
|
|
||||||
|
type GetReleaseByArtistAndTitlesNoMbzIDParams struct {
|
||||||
|
Column1 []string
|
||||||
|
ArtistID int32
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *Queries) GetReleaseByArtistAndTitlesNoMbzID(ctx context.Context, arg GetReleaseByArtistAndTitlesNoMbzIDParams) (ReleasesWithTitle, error) {
|
||||||
|
row := q.db.QueryRow(ctx, getReleaseByArtistAndTitlesNoMbzID, arg.Column1, arg.ArtistID)
|
||||||
|
var i ReleasesWithTitle
|
||||||
|
err := row.Scan(
|
||||||
|
&i.ID,
|
||||||
|
&i.MusicBrainzID,
|
||||||
|
&i.Image,
|
||||||
|
&i.VariousArtists,
|
||||||
|
&i.ImageSource,
|
||||||
|
&i.Title,
|
||||||
|
)
|
||||||
|
return i, err
|
||||||
|
}
|
||||||
|
|
||||||
const getReleaseByImageID = `-- name: GetReleaseByImageID :one
|
const getReleaseByImageID = `-- name: GetReleaseByImageID :one
|
||||||
SELECT id, musicbrainz_id, image, various_artists, image_source FROM releases
|
SELECT id, musicbrainz_id, image, various_artists, image_source FROM releases
|
||||||
WHERE image = $1 LIMIT 1
|
WHERE image = $1 LIMIT 1
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue