feat(db): add similarity sqlc queries (list-needing, get-by-mbids, upsert)
This commit is contained in:
@@ -29,6 +29,14 @@ type Artist struct {
|
||||
UpdatedAt pgtype.Timestamptz
|
||||
}
|
||||
|
||||
type ArtistSimilarity struct {
|
||||
ArtistAID pgtype.UUID
|
||||
ArtistBID pgtype.UUID
|
||||
Score float64
|
||||
Source string
|
||||
FetchedAt pgtype.Timestamptz
|
||||
}
|
||||
|
||||
type ContextualLike struct {
|
||||
ID pgtype.UUID
|
||||
UserID pgtype.UUID
|
||||
@@ -129,6 +137,14 @@ type Track struct {
|
||||
UpdatedAt pgtype.Timestamptz
|
||||
}
|
||||
|
||||
type TrackSimilarity struct {
|
||||
TrackAID pgtype.UUID
|
||||
TrackBID pgtype.UUID
|
||||
Score float64
|
||||
Source string
|
||||
FetchedAt pgtype.Timestamptz
|
||||
}
|
||||
|
||||
type User struct {
|
||||
ID pgtype.UUID
|
||||
Username string
|
||||
|
||||
@@ -0,0 +1,191 @@
|
||||
// Code generated by sqlc. DO NOT EDIT.
|
||||
// versions:
|
||||
// sqlc v1.27.0
|
||||
// source: similarity.sql
|
||||
|
||||
package dbq
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/jackc/pgx/v5/pgtype"
|
||||
)
|
||||
|
||||
const getArtistsByMBIDs = `-- name: GetArtistsByMBIDs :many
|
||||
SELECT id, mbid FROM artists WHERE mbid = ANY($1::text[])
|
||||
`
|
||||
|
||||
type GetArtistsByMBIDsRow struct {
|
||||
ID pgtype.UUID
|
||||
Mbid *string
|
||||
}
|
||||
|
||||
func (q *Queries) GetArtistsByMBIDs(ctx context.Context, dollar_1 []string) ([]GetArtistsByMBIDsRow, error) {
|
||||
rows, err := q.db.Query(ctx, getArtistsByMBIDs, dollar_1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []GetArtistsByMBIDsRow
|
||||
for rows.Next() {
|
||||
var i GetArtistsByMBIDsRow
|
||||
if err := rows.Scan(&i.ID, &i.Mbid); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const getTracksByMBIDs = `-- name: GetTracksByMBIDs :many
|
||||
SELECT id, mbid FROM tracks WHERE mbid = ANY($1::text[])
|
||||
`
|
||||
|
||||
type GetTracksByMBIDsRow struct {
|
||||
ID pgtype.UUID
|
||||
Mbid *string
|
||||
}
|
||||
|
||||
// Bulk in-library lookup: maps a slice of MBIDs back to local track IDs.
|
||||
func (q *Queries) GetTracksByMBIDs(ctx context.Context, dollar_1 []string) ([]GetTracksByMBIDsRow, error) {
|
||||
rows, err := q.db.Query(ctx, getTracksByMBIDs, dollar_1)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []GetTracksByMBIDsRow
|
||||
for rows.Next() {
|
||||
var i GetTracksByMBIDsRow
|
||||
if err := rows.Scan(&i.ID, &i.Mbid); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const listPlayedArtistsNeedingSimilarity = `-- name: ListPlayedArtistsNeedingSimilarity :many
|
||||
SELECT DISTINCT ar.id, ar.mbid
|
||||
FROM artists ar
|
||||
JOIN tracks t ON t.artist_id = ar.id
|
||||
JOIN play_events pe ON pe.track_id = t.id
|
||||
WHERE ar.mbid IS NOT NULL
|
||||
AND NOT EXISTS (
|
||||
SELECT 1 FROM artist_similarity asim
|
||||
WHERE asim.artist_a_id = ar.id
|
||||
AND asim.source = 'listenbrainz'
|
||||
AND asim.fetched_at > now() - interval '7 days'
|
||||
)
|
||||
ORDER BY ar.id
|
||||
LIMIT $1
|
||||
`
|
||||
|
||||
type ListPlayedArtistsNeedingSimilarityRow struct {
|
||||
ID pgtype.UUID
|
||||
Mbid *string
|
||||
}
|
||||
|
||||
func (q *Queries) ListPlayedArtistsNeedingSimilarity(ctx context.Context, limit int32) ([]ListPlayedArtistsNeedingSimilarityRow, error) {
|
||||
rows, err := q.db.Query(ctx, listPlayedArtistsNeedingSimilarity, limit)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []ListPlayedArtistsNeedingSimilarityRow
|
||||
for rows.Next() {
|
||||
var i ListPlayedArtistsNeedingSimilarityRow
|
||||
if err := rows.Scan(&i.ID, &i.Mbid); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const listPlayedTracksNeedingSimilarity = `-- name: ListPlayedTracksNeedingSimilarity :many
|
||||
SELECT DISTINCT t.id, t.mbid
|
||||
FROM tracks t
|
||||
JOIN play_events pe ON pe.track_id = t.id
|
||||
WHERE t.mbid IS NOT NULL
|
||||
AND NOT EXISTS (
|
||||
SELECT 1 FROM track_similarity ts
|
||||
WHERE ts.track_a_id = t.id
|
||||
AND ts.source = 'listenbrainz'
|
||||
AND ts.fetched_at > now() - interval '7 days'
|
||||
)
|
||||
ORDER BY t.id
|
||||
LIMIT $1
|
||||
`
|
||||
|
||||
type ListPlayedTracksNeedingSimilarityRow struct {
|
||||
ID pgtype.UUID
|
||||
Mbid *string
|
||||
}
|
||||
|
||||
// Tracks with at least one play, an MBID, and no fresh listenbrainz row
|
||||
// (no row at all, OR fetched_at older than 7 days). Used by the worker
|
||||
// to find work each tick. Bounded by $1.
|
||||
func (q *Queries) ListPlayedTracksNeedingSimilarity(ctx context.Context, limit int32) ([]ListPlayedTracksNeedingSimilarityRow, error) {
|
||||
rows, err := q.db.Query(ctx, listPlayedTracksNeedingSimilarity, limit)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []ListPlayedTracksNeedingSimilarityRow
|
||||
for rows.Next() {
|
||||
var i ListPlayedTracksNeedingSimilarityRow
|
||||
if err := rows.Scan(&i.ID, &i.Mbid); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const upsertArtistSimilarity = `-- name: UpsertArtistSimilarity :exec
|
||||
INSERT INTO artist_similarity (artist_a_id, artist_b_id, score, source, fetched_at)
|
||||
VALUES ($1, $2, $3, 'listenbrainz', now())
|
||||
ON CONFLICT (artist_a_id, artist_b_id, source)
|
||||
DO UPDATE SET score = EXCLUDED.score, fetched_at = EXCLUDED.fetched_at
|
||||
`
|
||||
|
||||
type UpsertArtistSimilarityParams struct {
|
||||
ArtistAID pgtype.UUID
|
||||
ArtistBID pgtype.UUID
|
||||
Score float64
|
||||
}
|
||||
|
||||
func (q *Queries) UpsertArtistSimilarity(ctx context.Context, arg UpsertArtistSimilarityParams) error {
|
||||
_, err := q.db.Exec(ctx, upsertArtistSimilarity, arg.ArtistAID, arg.ArtistBID, arg.Score)
|
||||
return err
|
||||
}
|
||||
|
||||
const upsertTrackSimilarity = `-- name: UpsertTrackSimilarity :exec
|
||||
INSERT INTO track_similarity (track_a_id, track_b_id, score, source, fetched_at)
|
||||
VALUES ($1, $2, $3, 'listenbrainz', now())
|
||||
ON CONFLICT (track_a_id, track_b_id, source)
|
||||
DO UPDATE SET score = EXCLUDED.score, fetched_at = EXCLUDED.fetched_at
|
||||
`
|
||||
|
||||
type UpsertTrackSimilarityParams struct {
|
||||
TrackAID pgtype.UUID
|
||||
TrackBID pgtype.UUID
|
||||
Score float64
|
||||
}
|
||||
|
||||
func (q *Queries) UpsertTrackSimilarity(ctx context.Context, arg UpsertTrackSimilarityParams) error {
|
||||
_, err := q.db.Exec(ctx, upsertTrackSimilarity, arg.TrackAID, arg.TrackBID, arg.Score)
|
||||
return err
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
-- name: ListPlayedTracksNeedingSimilarity :many
|
||||
-- Tracks with at least one play, an MBID, and no fresh listenbrainz row
|
||||
-- (no row at all, OR fetched_at older than 7 days). Used by the worker
|
||||
-- to find work each tick. Bounded by $1.
|
||||
SELECT DISTINCT t.id, t.mbid
|
||||
FROM tracks t
|
||||
JOIN play_events pe ON pe.track_id = t.id
|
||||
WHERE t.mbid IS NOT NULL
|
||||
AND NOT EXISTS (
|
||||
SELECT 1 FROM track_similarity ts
|
||||
WHERE ts.track_a_id = t.id
|
||||
AND ts.source = 'listenbrainz'
|
||||
AND ts.fetched_at > now() - interval '7 days'
|
||||
)
|
||||
ORDER BY t.id
|
||||
LIMIT $1;
|
||||
|
||||
-- name: ListPlayedArtistsNeedingSimilarity :many
|
||||
SELECT DISTINCT ar.id, ar.mbid
|
||||
FROM artists ar
|
||||
JOIN tracks t ON t.artist_id = ar.id
|
||||
JOIN play_events pe ON pe.track_id = t.id
|
||||
WHERE ar.mbid IS NOT NULL
|
||||
AND NOT EXISTS (
|
||||
SELECT 1 FROM artist_similarity asim
|
||||
WHERE asim.artist_a_id = ar.id
|
||||
AND asim.source = 'listenbrainz'
|
||||
AND asim.fetched_at > now() - interval '7 days'
|
||||
)
|
||||
ORDER BY ar.id
|
||||
LIMIT $1;
|
||||
|
||||
-- name: GetTracksByMBIDs :many
|
||||
-- Bulk in-library lookup: maps a slice of MBIDs back to local track IDs.
|
||||
SELECT id, mbid FROM tracks WHERE mbid = ANY($1::text[]);
|
||||
|
||||
-- name: GetArtistsByMBIDs :many
|
||||
SELECT id, mbid FROM artists WHERE mbid = ANY($1::text[]);
|
||||
|
||||
-- name: UpsertTrackSimilarity :exec
|
||||
INSERT INTO track_similarity (track_a_id, track_b_id, score, source, fetched_at)
|
||||
VALUES ($1, $2, $3, 'listenbrainz', now())
|
||||
ON CONFLICT (track_a_id, track_b_id, source)
|
||||
DO UPDATE SET score = EXCLUDED.score, fetched_at = EXCLUDED.fetched_at;
|
||||
|
||||
-- name: UpsertArtistSimilarity :exec
|
||||
INSERT INTO artist_similarity (artist_a_id, artist_b_id, score, source, fetched_at)
|
||||
VALUES ($1, $2, $3, 'listenbrainz', now())
|
||||
ON CONFLICT (artist_a_id, artist_b_id, source)
|
||||
DO UPDATE SET score = EXCLUDED.score, fetched_at = EXCLUDED.fetched_at;
|
||||
Reference in New Issue
Block a user