Files
minstrel/internal/db/migrations/0009_similarity.up.sql
T

34 lines
1.6 KiB
SQL

-- M4b: ListenBrainz similarity ingest. Two symmetric tables — tracks and
-- artists — both keyed by (a_id, b_id, source) so the schema reserves room
-- for additional similarity sources (musicbrainz_tag, user_cooccurrence)
-- alongside listenbrainz. M4b only writes 'listenbrainz' rows.
--
-- The (a_id, score DESC) index satisfies M4c's hot path: "for seed S, give
-- me top-N similar tracks/artists descending by score."
CREATE TABLE track_similarity (
track_a_id uuid NOT NULL REFERENCES tracks(id) ON DELETE CASCADE,
track_b_id uuid NOT NULL REFERENCES tracks(id) ON DELETE CASCADE,
score DOUBLE PRECISION NOT NULL,
source TEXT NOT NULL CHECK (source IN ('listenbrainz', 'musicbrainz_tag', 'user_cooccurrence')),
fetched_at timestamptz NOT NULL DEFAULT now(),
PRIMARY KEY (track_a_id, track_b_id, source),
CHECK (track_a_id <> track_b_id)
);
CREATE INDEX track_similarity_a_score_idx
ON track_similarity (track_a_id, score DESC);
CREATE TABLE artist_similarity (
artist_a_id uuid NOT NULL REFERENCES artists(id) ON DELETE CASCADE,
artist_b_id uuid NOT NULL REFERENCES artists(id) ON DELETE CASCADE,
score DOUBLE PRECISION NOT NULL,
source TEXT NOT NULL CHECK (source IN ('listenbrainz', 'musicbrainz_tag', 'user_cooccurrence')),
fetched_at timestamptz NOT NULL DEFAULT now(),
PRIMARY KEY (artist_a_id, artist_b_id, source),
CHECK (artist_a_id <> artist_b_id)
);
CREATE INDEX artist_similarity_a_score_idx
ON artist_similarity (artist_a_id, score DESC);