schema: add comic metadata and reading direction support
Add 14 new columns to media_items table for comprehensive comic and manga metadata support, including reading direction fields and universal metadata that applies to all media formats. New Columns: - Reading direction: manga_type (raw ComicInfo.xml field), reading_direction (computed) - Universal series: series_count, volume (apply to ebooks, audiobooks, comics) - Publisher info: imprint, age_rating (all formats) - Comic-specific: story_arc, is_black_and_white, alternate_info, scan_information, summary - Additional metadata: metadata_notes, community_rating, web_url Constraints: - manga_type CHECK: unknown, no, yes, yes_and_right_to_left - reading_direction CHECK: auto, ltr, rtl, vertical Indexes (8 new): - idx_media_items_reading_direction, idx_media_items_manga_type - idx_media_items_story_arc, idx_media_items_imprint - idx_media_items_age_rating, idx_media_items_series_count, idx_media_items_volume - idx_media_items_alternate_info_gin (GIN index for JSONB queries) Documentation: - Added COMMENT ON COLUMN for all 14 new fields - Distinctions between comic-specific and universal fields clearly documented This supports the ComicInfo.xml v2.0 standard with 29 fields and enables proper reading direction detection for manga, webtoons, and Western comics. Part of Phase 1: Database Schema Changes Implementation: IMPLEMENTATION_PLAN_MERGE_METADATA_READING_DIRECTION.md
This commit is contained in:
@@ -133,7 +133,40 @@ CREATE TABLE IF NOT EXISTS media_items (
|
|||||||
entitlement_id VARCHAR(255) UNIQUE,
|
entitlement_id VARCHAR(255) UNIQUE,
|
||||||
revision_number INTEGER DEFAULT 1,
|
revision_number INTEGER DEFAULT 1,
|
||||||
kobo_content_id VARCHAR(255),
|
kobo_content_id VARCHAR(255),
|
||||||
kobo_metadata JSONB
|
kobo_metadata JSONB,
|
||||||
|
-- Manga and comic reading direction support
|
||||||
|
-- Stores raw Manga field from ComicInfo.xml
|
||||||
|
manga_type VARCHAR(30) DEFAULT 'unknown',
|
||||||
|
reading_direction VARCHAR(20) DEFAULT 'auto',
|
||||||
|
CHECK (manga_type IN ('unknown', 'no', 'yes', 'yes_and_right_to_left')),
|
||||||
|
CHECK (reading_direction IN ('auto', 'ltr', 'rtl', 'vertical')),
|
||||||
|
|
||||||
|
-- Universal series information (applies to ALL formats: ebooks, audiobooks, comics)
|
||||||
|
series_count INTEGER, -- Total items in series (from ComicInfo Count field, or book series count)
|
||||||
|
volume INTEGER, -- Volume/omnibus number for collected editions
|
||||||
|
|
||||||
|
-- Universal publisher and classification (applies to ALL formats)
|
||||||
|
imprint VARCHAR(255), -- Publisher imprint (e.g., Vertigo, HarperCollinsEpic)
|
||||||
|
age_rating VARCHAR(20), -- Age rating: Everyone, Teen, Mature, Adult (applies to all formats)
|
||||||
|
web_url VARCHAR(500), -- URL to info page (Goodreads, ComicVine, MangaUpdates, Audible, etc.)
|
||||||
|
|
||||||
|
-- Comic-specific fields
|
||||||
|
story_arc VARCHAR(255), -- Story arc name (e.g., "The Dark Phoenix Saga", "Civil War")
|
||||||
|
is_black_and_white BOOLEAN, -- Black and white flag (mostly comics, some illustrated books)
|
||||||
|
|
||||||
|
-- Additional metadata (applies to all formats)
|
||||||
|
metadata_notes TEXT, -- Notes from metadata files (ComicInfo.xml, EPUB, PDF) - distinct from user notes
|
||||||
|
community_rating DECIMAL(3,1), -- Pre-existing community rating from metadata (0.0-10.0) - distinct from user ratings
|
||||||
|
|
||||||
|
-- Alternate series information (JSONB for flexible schema - comic-specific)
|
||||||
|
alternate_info JSONB, -- Stores AlternateSeries, AlternateNumber, AlternateCount
|
||||||
|
-- Example: {"alternate_series": "Ultimate X-Men", "alternate_number": 1, "alternate_count": 12}
|
||||||
|
|
||||||
|
-- Scan and publication metadata (comic-specific)
|
||||||
|
scan_information TEXT, -- Scan information (scanner group, resolution, etc.)
|
||||||
|
|
||||||
|
-- Summary (distinct from description - may merge with Calibre description)
|
||||||
|
summary TEXT -- Summary from ComicInfo.xml (may be merged with description from Calibre)
|
||||||
);
|
);
|
||||||
|
|
||||||
-- Add GIN indexes for fast array searches
|
-- Add GIN indexes for fast array searches
|
||||||
@@ -387,6 +420,46 @@ CREATE INDEX IF NOT EXISTS idx_media_items_copyright_year ON media_items(copyrig
|
|||||||
CREATE INDEX IF NOT EXISTS idx_media_items_page_count ON media_items(page_count);
|
CREATE INDEX IF NOT EXISTS idx_media_items_page_count ON media_items(page_count);
|
||||||
CREATE INDEX IF NOT EXISTS idx_media_items_series ON media_items(series);
|
CREATE INDEX IF NOT EXISTS idx_media_items_series ON media_items(series);
|
||||||
|
|
||||||
|
-- Index for filtering by reading direction (for manga/comic libraries)
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_media_items_reading_direction
|
||||||
|
ON media_items(reading_direction)
|
||||||
|
WHERE reading_direction IS NOT NULL;
|
||||||
|
|
||||||
|
-- Index for filtering by story arc (comic-specific)
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_media_items_story_arc
|
||||||
|
ON media_items(story_arc)
|
||||||
|
WHERE story_arc IS NOT NULL;
|
||||||
|
|
||||||
|
-- Index for filtering by imprint (universal - all formats)
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_media_items_imprint
|
||||||
|
ON media_items(imprint)
|
||||||
|
WHERE imprint IS NOT NULL;
|
||||||
|
|
||||||
|
-- Index for filtering by age rating (universal - all formats)
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_media_items_age_rating
|
||||||
|
ON media_items(age_rating)
|
||||||
|
WHERE age_rating IS NOT NULL;
|
||||||
|
|
||||||
|
-- Index for filtering by manga type (comic-specific)
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_media_items_manga_type
|
||||||
|
ON media_items(manga_type)
|
||||||
|
WHERE manga_type IS NOT NULL;
|
||||||
|
|
||||||
|
-- Index for filtering by series count (universal - all formats)
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_media_items_series_count
|
||||||
|
ON media_items(series_count)
|
||||||
|
WHERE series_count IS NOT NULL;
|
||||||
|
|
||||||
|
-- Index for filtering by volume (universal - all formats)
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_media_items_volume
|
||||||
|
ON media_items(volume)
|
||||||
|
WHERE volume IS NOT NULL;
|
||||||
|
|
||||||
|
-- GIN index for alternate_info JSONB queries (comic-specific)
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_media_items_alternate_info_gin
|
||||||
|
ON media_items USING GIN (alternate_info)
|
||||||
|
WHERE alternate_info IS NOT NULL;
|
||||||
|
|
||||||
-- Progress and ratings indexes
|
-- Progress and ratings indexes
|
||||||
CREATE INDEX IF NOT EXISTS idx_reading_progress_media_item_id ON reading_progress(media_item_id);
|
CREATE INDEX IF NOT EXISTS idx_reading_progress_media_item_id ON reading_progress(media_item_id);
|
||||||
CREATE INDEX IF NOT EXISTS idx_reading_progress_user_id ON reading_progress(user_id);
|
CREATE INDEX IF NOT EXISTS idx_reading_progress_user_id ON reading_progress(user_id);
|
||||||
@@ -477,6 +550,26 @@ COMMENT ON COLUMN media_items.goodreads_id IS 'Goodreads book identifier for int
|
|||||||
COMMENT ON COLUMN media_items.openlibrary_id IS 'Open Library identifier for integration';
|
COMMENT ON COLUMN media_items.openlibrary_id IS 'Open Library identifier for integration';
|
||||||
COMMENT ON COLUMN media_items.google_books_id IS 'Google Books identifier for integration';
|
COMMENT ON COLUMN media_items.google_books_id IS 'Google Books identifier for integration';
|
||||||
|
|
||||||
|
-- Comic-specific fields
|
||||||
|
COMMENT ON COLUMN media_items.manga_type IS 'Raw Manga field from ComicInfo.xml: unknown, no, yes, yes_and_right_to_left';
|
||||||
|
COMMENT ON COLUMN media_items.reading_direction IS 'Computed reading direction: auto, ltr (left-to-right), rtl (right-to-left), vertical (webtoons/manhwa)';
|
||||||
|
COMMENT ON COLUMN media_items.story_arc IS 'Story arc name for grouping related issues (e.g., "The Dark Phoenix Saga", "Civil War")';
|
||||||
|
COMMENT ON COLUMN media_items.is_black_and_white IS 'Black and white comic flag from ComicInfo.xml';
|
||||||
|
COMMENT ON COLUMN media_items.alternate_info IS 'Alternate series information as JSONB: {alternate_series, alternate_number, alternate_count}';
|
||||||
|
COMMENT ON COLUMN media_items.scan_information IS 'Scan information from ComicInfo.xml (scanner group, resolution, etc.)';
|
||||||
|
|
||||||
|
-- Universal fields (apply to ebooks, audiobooks, comics)
|
||||||
|
COMMENT ON COLUMN media_items.series_count IS 'Total items in series (from ComicInfo.xml Count field, or book series count)';
|
||||||
|
COMMENT ON COLUMN media_items.volume IS 'Volume/omnibus number for collected editions';
|
||||||
|
COMMENT ON COLUMN media_items.imprint IS 'Publisher imprint/subdivision (e.g., Vertigo, HarperCollinsEpic, DC Black Label)';
|
||||||
|
COMMENT ON COLUMN media_items.age_rating IS 'Age rating from metadata: Everyone, Teen, Mature, Adult (applies to all formats)';
|
||||||
|
COMMENT ON COLUMN media_items.web_url IS 'URL to info page (Goodreads, ComicVine, MangaUpdates, Audible, etc.)';
|
||||||
|
|
||||||
|
-- Additional metadata (applies to all formats)
|
||||||
|
COMMENT ON COLUMN media_items.metadata_notes IS 'Notes from metadata files (ComicInfo.xml, EPUB, PDF) - distinct from user notes in media_notes table';
|
||||||
|
COMMENT ON COLUMN media_items.community_rating IS 'Pre-existing community rating from metadata files (scale 0.0-10.0) - distinct from user ratings in media_ratings table';
|
||||||
|
COMMENT ON COLUMN media_items.summary IS 'Summary from ComicInfo.xml (may be merged with description from Calibre)';
|
||||||
|
|
||||||
-- Library Type File Extensions Notes:
|
-- Library Type File Extensions Notes:
|
||||||
-- - Ebooks: .epub, .pdf, .mobi, .azw, .azw3, .txt, .rtf, .doc, .docx, .lit, .fb2, .pdb
|
-- - Ebooks: .epub, .pdf, .mobi, .azw, .azw3, .txt, .rtf, .doc, .docx, .lit, .fb2, .pdb
|
||||||
-- - Comics: .cbz, .cbr, .cb7, .cbt, .pdf
|
-- - Comics: .cbz, .cbr, .cb7, .cbt, .pdf
|
||||||
|
|||||||
Reference in New Issue
Block a user