Add database structure documentation

This commit is contained in:
Claudio Ortolina
2025-04-03 09:47:42 +01:00
parent bc72ab7e7f
commit c029e4618b
2 changed files with 125 additions and 0 deletions
+4
View File
@@ -90,6 +90,10 @@ The application is setup for deployment on Fly.io - just make sure you edit
See the `.github` folder.
## Architecture
See the `docs` folder.
## Favicons
This favicon was generated using the following graphics from Twitter Twemoji:
+121
View File
@@ -0,0 +1,121 @@
# Database Structure
This document describes the database structure of the Music Library application.
## Entity Relationship Diagram
```mermaid
erDiagram
RECORDS {
uuid id PK
string type
string format
string title
uuid musicbrainz_id
string[] genres
string cover_url
blob cover_data
string cover_hash
map musicbrainz_data
string[] release_ids
string[] included_release_group_ids
datetime purchased_at
string release
map artists
datetime inserted_at
datetime updated_at
}
RECORDS_SEARCH_INDEX {
uuid id PK
string type
string format
string title
uuid musicbrainz_id
string[] genres
string[] release_ids
string[] included_release_group_ids
string cover_hash
datetime purchased_at
string release
map artists
}
ARTIST_RECORDS {
uuid musicbrainz_id
uuid record_id
map artist
}
RECORDS ||--o{ RECORDS_SEARCH_INDEX : "syncs via triggers"
RECORDS ||--o{ ARTIST_RECORDS : "extracted from artists JSON"
```
## Tables Description
### Records
The main table storing music records. Key features:
- Uses UUID as primary key
- Stores basic record information (title, type, format, year)
- Includes MusicBrainz integration with IDs and additional data
- Stores cover image data and URLs
- Embeds artists data directly in a JSON field
- Includes timestamps for record keeping
### Records Search Index
A virtual FTS5 (Full Text Search) table that mirrors the records table for efficient searching:
- Automatically synced with the records table via triggers
- Optimized for full-text search operations
- Contains most fields from the records table
- Some fields are marked as UNINDEXED for efficiency
### Views
#### Artist Records View
A view that extracts artist information from the embedded JSON in the records table:
```sql
CREATE VIEW artist_records AS
SELECT json_extract(json_each.value, '$.musicbrainz_id') AS musicbrainz_id,
records.id AS record_id,
json_each.value as artist
FROM records,
json_each(records.artists)
```
### Triggers
The following triggers maintain the search index:
1. `records_search_index_before_update`: Removes old record data from search index before updates
2. `records_search_index_before_delete`: Removes record data from search index before deletion
3. `records_after_insert`: Inserts new record data into search index after record creation
4. `records_after_update`: Updates record data in search index after record updates
### Indices
The following indices are maintained for performance:
1. On `records`:
- `format`
- `title`
- `musicbrainz_id`
- `purchased_at`
- `included_release_group_ids`
- `release_ids`
## Notes
1. The database uses SQLite as the primary database.
2. Artists data is embedded directly in the records table as JSON/map data, rather than having a separate table.
3. The search index is implemented using SQLite's FTS5 extension for efficient full-text search capabilities.
4. Where needed queries use SQLite's `unicode` extension to filter/sort over UTF-8 data.
5. The database supports both collection and wishlist functionality through the `purchased_at` field:
- Records with `purchased_at IS NOT NULL` are in the collection
- Records with `purchased_at IS NULL` are in the wishlist