34 lines
1.6 KiB
SQL
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);
|