Про флибусту
Dec. 10th, 2022 04:51 pm![[personal profile]](https://www.dreamwidth.org/img/silk/identity/user.png)
Скачавши очередное (декабрьское) обновление флибусты, решил подумать о том, как бы себе сделать правильную искалку по ее метаинформации. На основании того, что я знаю о XML-схеме fb2-файлов и о том как устроены индексные (inpx) файлы флибусты. (ну и о том что флибустьеры не правят метаинфомрацию в файлах, поэтому корректная метаинформация содержится (если содержится) только в inp-файлах.
Ну то есть я знаю что у MyHomeLib схема базы кривая, ее какой-то девопс дизайнил, который не то что Дейта - Граббера не читал.
Ну для начала взял pgmodeller и нарисовал ER-диаграмму каталога библиотеки fb2-файлов. Из чисто флибустовских сущностей добавил туда только понятие архива. В смысле того zip-файла в котором в скачанном из торрентов мирроре лежит нужный f2.
Получилось 10 таблиц. Сущностей в принципе не так уж много
- book
- author (он же translator)
- sequence
- lang (классификатор для полей lang и srclang в таблице book)
- genre
Но везде же отношения m:n и нужны развязывающие таблички. А в табличке устанавливающей соответствие между книгой и серией еще и содержательное поле number лежит. И ведь на него даже NOT NULL не повесишь, я же знаю что полно есть в архиве книг у которых серия без номера.
Вообще я чувствую, что над жанрами еще табличка транзитивного замыкания нужна чтобы из них дерево выстроить. Но поскольку fb2-шной концепции жанров я никогда не понимал (и подозреваю что большая часть оцифровщиков тоже и жанры они в fb2-файлах ставили от балды) занимтаься этим мне лень.
Вот теперь думаю - писать парсилку inp-файлов в эту схему в sqlite, или уж сразу постгрес использовать. (и импортить туда весь текст fb2 на предмет организации полнотекстового поиска).
Для интересующихся сдизайненную схему положу под кат:
CREATE TABLE lang ( lang_code char(3) NOT NULL, lang_name text NOT NULL, CONSTRAINT lang_pk PRIMARY KEY (lang_code) ); CREATE TABLE archive ( archive_id serial NOT NULL, archive_name text NOT NULL, CONSTRAINT archive_pk PRIMARY KEY (archive_id) ); CREATE TABLE book ( book_id int8 NOT NULL, title text NOT NULL, file text NOT NULL, deleted boolean NOT NULL DEFAULT false, writedate datetime, lang char(3), srclang char(3), archive smallint NOT NULL, CONSTRAINT book_pk PRIMARY KEY (book_id), FOREIGN KEY (lang) REFERENCES lang(lang_code), FOREIGN KEY (srclang) REFERENCES lang(lang_code), FOREIGN KEY (archive) REFERENCES archive(archive_id) ); CREATE TABLE author ( author_id int4 NOT NULL, first_name text, middle_name text, last_name text, nickname text, CONSTRAINT author_pk PRIMARY KEY (author_id) ); CREATE TABLE seq ( sequence_id int4 NOT NULL, name text NOT NULL, CONSTRAINT seq_pk PRIMARY KEY (sequence_id) ); CREATE TABLE replaces ( old_book_id int8 NOT NULL, new_book_id int8 NOT NULL, CONSTRAINT replaces_pk PRIMARY KEY (old_book_id,new_book_id), FOREIGN KEY (old_book_id) REFERENCES book(book_id), FOREIGN KEY (new_book_id) REFERENCES book(book_id) ); CREATE TABLE book_author ( book_id int8 NOT NULL, author_id int4 NOT NULL, CONSTRAINT book_author_pk PRIMARY KEY (book_id,author_id), FOREIGN KEY (book_id) REFERENCES book(book_id), FOREIGN KEY (author_id) REFERENCES author(author_id) ); CREATE TABLE book_translator ( book_id int8 NOT NULL, translator_id int4 NOT NULL, CONSTRAINT book_translator_pk PRIMARY KEY (book_id,translator_id), FOREIGN KEY (book_id) REFERENCES book(book_id), FOREIGN KEY (translator_id) REFERENCES author(author_id) ); CREATE TABLE book_seq ( book_id int8 NOT NULL, sequence_id int4 NOT NULL, sequence_number int4, CONSTRAINT book_seq_pk PRIMARY KEY (book_id,sequence_id), FOREIGN KEY (book_id) REFERENCES book(book_id), FOREIGN KEY (sequence_id) REFERENCES seq(sequence_id) ); CREATE TABLE genre ( genre_id varchar(20) NOT NULL, genre_name text NOT NULL, CONSTRAINT genre_pk PRIMARY KEY (genre_id) ); CREATE TABLE book_genre ( book_id int8 NOT NULL, genre_id varchar(20) NOT NULL, CONSTRAINT book_genre_pk PRIMARY KEY (book_id,genre_id), FOREIGN KEY (book_id) REFERENCES book(book_id), FOREIGN KEY (genre_id) REFERENCES genre(genre_id) );
Что характерно, пока я причесывал этот SQL скрипт так, чтобы его сожрал sqlite, его объем сократился в 2.5 раза, а из содержательной информации потерялись только имена констрейнтов внешних ключей (и то можно было бы сохранить).
no subject
Date: 2022-12-12 07:24 am (UTC)Здесь должно быть все, но наличие описаний авторов я не проверял.
no subject
Date: 2022-12-12 07:39 am (UTC)Будет проблема синхронизации. Есть основания верить что inpx файл в архиве соответствует тому же моменту времени, что и книги в том же архиве. А вот про отдельную страничку этого сказать нельзя.
no subject
Date: 2022-12-12 08:18 am (UTC)