vitus_wagner: My photo 2005 (Default)
vitus_wagner ([personal profile] vitus_wagner) wrote2022-12-10 04:51 pm
Entry tags:

Про флибусту

Скачавши очередное (декабрьское) обновление флибусты, решил подумать о том, как бы себе сделать правильную искалку по ее метаинформации. На основании того, что я знаю о XML-схеме fb2-файлов и о том как устроены индексные (inpx) файлы флибусты. (ну и о том что флибустьеры не правят метаинфомрацию в файлах, поэтому корректная метаинформация содержится (если содержится) только в inp-файлах.

Ну то есть я знаю что у MyHomeLib схема базы кривая, ее какой-то девопс дизайнил, который не то что Дейта - Граббера не читал.

Ну для начала взял pgmodeller и нарисовал ER-диаграмму каталога библиотеки fb2-файлов. Из чисто флибустовских сущностей добавил туда только понятие архива. В смысле того zip-файла в котором в скачанном из торрентов мирроре лежит нужный f2.

Получилось 10 таблиц. Сущностей в принципе не так уж много

  1. book
  2. author (он же translator)
  3. sequence
  4. lang (классификатор для полей lang и srclang в таблице book)
  5. 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 раза, а из содержательной информации потерялись только имена констрейнтов внешних ключей (и то можно было бы сохранить).

[personal profile] vikarti_anantra 2022-12-10 04:25 pm (UTC)(link)
А postgres на домашнем сервере с разумными требованиями к ресурсам сможет работать с полнотекстовым поиском по загруженой туда полной базе fb2шек с флибусты?

У меня вот полнотекстовый поиск для себя есть через спецплагин к calibre и recoll (штатный поиск в Calibre 6 - неудобный) но у меня объемы базы Calibre целиком - около 100 Gb и там не только fb2 а объем fb2 насколько помню где то 300-400 Gb архивов.

[personal profile] vikarti_anantra 2022-12-10 05:32 pm (UTC)(link)
Для меня поиск на смартфоне - это мечта. Которую непонятно как реализовать
(пока выкручиваюсь кое как поиском на компе и развитой системой тегов)ю

Было бы интересно посмотреть что у вас в итоге получится если это хоть как то публично в итоге будет.