![[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
У меня вот полнотекстовый поиск для себя есть через спецплагин к calibre и recoll (штатный поиск в Calibre 6 - неудобный) но у меня объемы базы Calibre целиком - около 100 Gb и там не только fb2 а объем fb2 насколько помню где то 300-400 Gb архивов.
no subject
Ну у меня домашний сервер сейчас с неразумными требованиями по ресурсам. Рассчитанный на параллельный запуск минимум десяти регрессионных тестов того самого постгреса. То есть конечно не Big Beast Раймонда но всё же.
Но вообще требования к ресурсам у постгресовского полнотекстового поиска не такие уж большие.
Опять же большую часть тех архивов fb2 сославляют иллюстрации в base64. Если при покладании в поисковую базу аккуратно парсить fb2 и выдирать из них только текст, то объем существенно уменьшится.
Правда если быть гурманами до конца, там надо кое-какую метаинформацию в отдельные поля складывать чтобы при поиске учитываьть с большим весом. Но ее такой немного. Задача вообще-то состоит в том чтобы полнотекстовый поиск работал не на "домашнем сервере с разумными требованиями к ресурсам", а "на смартфоне с большой SDD-картой". Поскольку по нынешним временам полутерабайтная база считается маленькой, должно бы получиться. В конце концов будет короший тест-кейс для той команды, которая у нас сейчас полнтекстовый поиск поддерживает.
no subject
(пока выкручиваюсь кое как поиском на компе и развитой системой тегов)ю
Было бы интересно посмотреть что у вас в итоге получится если это хоть как то публично в итоге будет.
no subject
На самом деле на смартфоне у менся сейчас лежит не полный миррор флибусты а всего около 2 с половиной гигабайт книг (далеко не все из которых есть на флибусте, там полно всяких англоязычных с archive.org, gutenberg и даже с амазона).
Вот что с таким объемом текста постгрес на паре гигов справится (А столько в смартфоне есть) я уверен.
Но пока я развлекаюсь с полнотекстовым поиском в sqlite. Там правда с токенайзерами как-то плоховато - hunspell-овские в отличие от постгреса туда не прикручиваются. А поиск по русскому тексту без токенайзера это как-то даже не интересно.
На самом деле полнотекстовый поиск для меня задача далеко не первоочередная. Первоочередная это поддержка миррора флибусты + система исправления ошибок в нём. А то я знаю что на этой флибусте в fb2 есть несколько тысяч файлов с not well-formed xml, а уж сколько не соответствующих XML Schema FictionBook 2.1 - и подумать страшно. Полнотекстовый поиск по архиву fb2 когда-то делат
nataraj. Но не помню подробностей.