vitus_wagner: My photo 2005 (Default)
[personal profile] vitus_wagner

Скачавши очередное (декабрьское) обновление флибусты, решил подумать о том, как бы себе сделать правильную искалку по ее метаинформации. На основании того, что я знаю о 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 раза, а из содержательной информации потерялись только имена констрейнтов внешних ключей (и то можно было бы сохранить).

Date: 2022-12-12 07:24 am (UTC)
2e8: (Default)
From: [personal profile] 2e8
http://flibusta.is/sql/

Здесь должно быть все, но наличие описаний авторов я не проверял.

Date: 2022-12-12 08:18 am (UTC)
2e8: (Default)
From: [personal profile] 2e8
Может так, а может и не так. Я сопоставляю файлы с записями в базе по md5. Это самый надежный метод.

Profile

vitus_wagner: My photo 2005 (Default)
vitus_wagner

June 2025

S M T W T F S
1 23 4 56 7
89 1011 12 1314
15161718192021
22232425262728
2930     

Most Popular Tags

Page Summary

Style Credit

Expand Cut Tags

No cut tags
Page generated Jun. 14th, 2025 10:33 am
Powered by Dreamwidth Studios