feat: initial implementation of metadata aggregator
- gRPC service with MusicBrainz provider - PostgreSQL schema with migrations - Service layer with database-first caching - Repository pattern for data access - YAML configuration support - Research documentation for 17 music metadata projects
This commit is contained in:
@@ -0,0 +1,199 @@
|
||||
-- Core Entities
|
||||
|
||||
CREATE TABLE artists (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
name TEXT NOT NULL,
|
||||
sort_name TEXT,
|
||||
artist_type TEXT,
|
||||
country TEXT,
|
||||
formed_date DATE,
|
||||
disbanded_date DATE,
|
||||
description TEXT,
|
||||
image_url TEXT,
|
||||
source TEXT NOT NULL,
|
||||
source_id TEXT,
|
||||
created_at TIMESTAMPTZ DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE TABLE works (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
title TEXT NOT NULL,
|
||||
work_type TEXT,
|
||||
language TEXT,
|
||||
source TEXT NOT NULL,
|
||||
source_id TEXT,
|
||||
created_at TIMESTAMPTZ DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE TABLE tracks (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
work_id UUID REFERENCES works(id),
|
||||
title TEXT NOT NULL,
|
||||
duration_ms INT,
|
||||
isrc TEXT,
|
||||
explicit BOOLEAN DEFAULT false,
|
||||
source TEXT NOT NULL,
|
||||
source_id TEXT,
|
||||
created_at TIMESTAMPTZ DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE TABLE labels (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
name TEXT NOT NULL,
|
||||
country TEXT,
|
||||
founded_date DATE,
|
||||
source TEXT NOT NULL,
|
||||
source_id TEXT,
|
||||
created_at TIMESTAMPTZ DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE TABLE albums (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
label_id UUID REFERENCES labels(id),
|
||||
title TEXT NOT NULL,
|
||||
album_type TEXT,
|
||||
release_date DATE,
|
||||
upc TEXT,
|
||||
total_tracks INT,
|
||||
total_discs INT DEFAULT 1,
|
||||
cover_url TEXT,
|
||||
source TEXT NOT NULL,
|
||||
source_id TEXT,
|
||||
created_at TIMESTAMPTZ DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE TABLE genres (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
name TEXT NOT NULL UNIQUE,
|
||||
parent_id UUID REFERENCES genres(id)
|
||||
);
|
||||
|
||||
-- Relationships
|
||||
|
||||
CREATE TABLE track_artists (
|
||||
track_id UUID REFERENCES tracks(id) ON DELETE CASCADE,
|
||||
artist_id UUID REFERENCES artists(id) ON DELETE CASCADE,
|
||||
role TEXT DEFAULT 'primary',
|
||||
position INT DEFAULT 0,
|
||||
PRIMARY KEY (track_id, artist_id, role)
|
||||
);
|
||||
|
||||
CREATE TABLE album_artists (
|
||||
album_id UUID REFERENCES albums(id) ON DELETE CASCADE,
|
||||
artist_id UUID REFERENCES artists(id) ON DELETE CASCADE,
|
||||
role TEXT DEFAULT 'primary',
|
||||
position INT DEFAULT 0,
|
||||
PRIMARY KEY (album_id, artist_id, role)
|
||||
);
|
||||
|
||||
CREATE TABLE album_tracks (
|
||||
album_id UUID REFERENCES albums(id) ON DELETE CASCADE,
|
||||
track_id UUID REFERENCES tracks(id) ON DELETE CASCADE,
|
||||
disc_number INT DEFAULT 1,
|
||||
track_number INT NOT NULL,
|
||||
PRIMARY KEY (album_id, track_id)
|
||||
);
|
||||
|
||||
CREATE TABLE work_artists (
|
||||
work_id UUID REFERENCES works(id) ON DELETE CASCADE,
|
||||
artist_id UUID REFERENCES artists(id) ON DELETE CASCADE,
|
||||
role TEXT DEFAULT 'writer',
|
||||
PRIMARY KEY (work_id, artist_id, role)
|
||||
);
|
||||
|
||||
CREATE TABLE artist_genres (
|
||||
artist_id UUID REFERENCES artists(id) ON DELETE CASCADE,
|
||||
genre_id UUID REFERENCES genres(id) ON DELETE CASCADE,
|
||||
PRIMARY KEY (artist_id, genre_id)
|
||||
);
|
||||
|
||||
CREATE TABLE album_genres (
|
||||
album_id UUID REFERENCES albums(id) ON DELETE CASCADE,
|
||||
genre_id UUID REFERENCES genres(id) ON DELETE CASCADE,
|
||||
PRIMARY KEY (album_id, genre_id)
|
||||
);
|
||||
|
||||
CREATE TABLE similar_artists (
|
||||
artist_id UUID REFERENCES artists(id) ON DELETE CASCADE,
|
||||
similar_artist_id UUID REFERENCES artists(id) ON DELETE CASCADE,
|
||||
score REAL DEFAULT 0.5,
|
||||
PRIMARY KEY (artist_id, similar_artist_id)
|
||||
);
|
||||
|
||||
-- Content
|
||||
|
||||
CREATE TABLE lyrics (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
track_id UUID REFERENCES tracks(id) ON DELETE CASCADE,
|
||||
content TEXT,
|
||||
synced_content JSONB,
|
||||
language TEXT,
|
||||
source TEXT NOT NULL,
|
||||
source_id TEXT,
|
||||
created_at TIMESTAMPTZ DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE TABLE playlists (
|
||||
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
|
||||
name TEXT NOT NULL,
|
||||
description TEXT,
|
||||
is_public BOOLEAN DEFAULT true,
|
||||
cover_url TEXT,
|
||||
created_at TIMESTAMPTZ DEFAULT now(),
|
||||
updated_at TIMESTAMPTZ DEFAULT now()
|
||||
);
|
||||
|
||||
CREATE TABLE playlist_tracks (
|
||||
playlist_id UUID REFERENCES playlists(id) ON DELETE CASCADE,
|
||||
track_id UUID REFERENCES tracks(id) ON DELETE CASCADE,
|
||||
position INT NOT NULL,
|
||||
added_at TIMESTAMPTZ DEFAULT now(),
|
||||
PRIMARY KEY (playlist_id, track_id)
|
||||
);
|
||||
|
||||
-- External IDs
|
||||
|
||||
CREATE TABLE artist_external_ids (
|
||||
artist_id UUID REFERENCES artists(id) ON DELETE CASCADE,
|
||||
source TEXT NOT NULL,
|
||||
source_id TEXT NOT NULL,
|
||||
url TEXT,
|
||||
fetched_at TIMESTAMPTZ DEFAULT now(),
|
||||
PRIMARY KEY (artist_id, source, source_id)
|
||||
);
|
||||
|
||||
CREATE TABLE album_external_ids (
|
||||
album_id UUID REFERENCES albums(id) ON DELETE CASCADE,
|
||||
source TEXT NOT NULL,
|
||||
source_id TEXT NOT NULL,
|
||||
url TEXT,
|
||||
fetched_at TIMESTAMPTZ DEFAULT now(),
|
||||
PRIMARY KEY (album_id, source, source_id)
|
||||
);
|
||||
|
||||
CREATE TABLE track_external_ids (
|
||||
track_id UUID REFERENCES tracks(id) ON DELETE CASCADE,
|
||||
source TEXT NOT NULL,
|
||||
source_id TEXT NOT NULL,
|
||||
url TEXT,
|
||||
fetched_at TIMESTAMPTZ DEFAULT now(),
|
||||
PRIMARY KEY (track_id, source, source_id)
|
||||
);
|
||||
|
||||
-- Indexes
|
||||
|
||||
CREATE INDEX idx_artists_name ON artists(name);
|
||||
CREATE INDEX idx_artists_source ON artists(source, source_id);
|
||||
CREATE INDEX idx_tracks_isrc ON tracks(isrc) WHERE isrc IS NOT NULL;
|
||||
CREATE INDEX idx_tracks_source ON tracks(source, source_id);
|
||||
CREATE INDEX idx_albums_upc ON albums(upc) WHERE upc IS NOT NULL;
|
||||
CREATE INDEX idx_albums_source ON albums(source, source_id);
|
||||
CREATE INDEX idx_albums_release_date ON albums(release_date);
|
||||
CREATE INDEX idx_genres_name ON genres(name);
|
||||
CREATE INDEX idx_lyrics_track_id ON lyrics(track_id);
|
||||
CREATE INDEX idx_playlist_tracks_position ON playlist_tracks(playlist_id, position);
|
||||
Reference in New Issue
Block a user