Первоначальные данные
This commit is contained in:
commit
f61fc0016c
4 files changed
+162
No files matched your search
@@ -0,0 +1,33 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
# ============================================================
|
||||||
|
# Скрипт инициализации базы данных
|
||||||
|
# Использование: ./init_db.sh [DB_CONN]
|
||||||
|
# ============================================================
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
DB_CONN="${1:-dbname=books user=postgres password=Karabas@Barabas host=172.20.0.4}"
|
||||||
|
|
||||||
|
echo "=== Инициализация базы данных ==="
|
||||||
|
echo "Подключение: $DB_CONN"
|
||||||
|
echo ""
|
||||||
|
|
||||||
|
# Проверяем соединение
|
||||||
|
if ! psql "$DB_CONN" -c "SELECT 1" > /dev/null 2>&1; then
|
||||||
|
echo "ОШИБКА: Не удалось подключиться к базе данных"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "1. Создание таблиц..."
|
||||||
|
psql "$DB_CONN" -f /app/sql/01_create_tables.sql
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "2. Создание индексов..."
|
||||||
|
psql "$DB_CONN" -f /app/sql/02_create_indexes.sql
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "3. Загрузка жанров..."
|
||||||
|
python3 /app/scripts/parse_genres.py /app/data/genres.xml "$DB_CONN"
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "=== Готово! ==="
|
||||||
@@ -0,0 +1,74 @@
|
|||||||
|
-- ============================================================
|
||||||
|
-- Схема базы данных для Домашней библиотеки
|
||||||
|
-- PostgreSQL 14+
|
||||||
|
-- ============================================================
|
||||||
|
|
||||||
|
-- Авторы
|
||||||
|
CREATE TABLE IF NOT EXISTS authors (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
full_name TEXT NOT NULL UNIQUE, -- "Пелевин,Виктор,Олегович"
|
||||||
|
last_name TEXT NOT NULL, -- "Пелевин"
|
||||||
|
first_name TEXT, -- "Виктор"
|
||||||
|
middle_name TEXT, -- "Олегович"
|
||||||
|
name_hash TEXT UNIQUE, -- MD5 от full_name (lowercase)
|
||||||
|
first_letter TEXT NOT NULL, -- первая буква фамилии (lowercase)
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Серии
|
||||||
|
CREATE TABLE IF NOT EXISTS series (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
name TEXT NOT NULL UNIQUE, -- "Плоский мир"
|
||||||
|
name_hash TEXT UNIQUE, -- MD5 от name (lowercase)
|
||||||
|
first_letter TEXT, -- первая буква названия
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Жанры (справочник из genres.xml + кастомные из inpx)
|
||||||
|
CREATE TABLE IF NOT EXISTS genres (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
code TEXT NOT NULL UNIQUE, -- "sf_history", "popadanec"
|
||||||
|
title_ru TEXT, -- "Альтернативная история"
|
||||||
|
title_en TEXT, -- "Alternative history"
|
||||||
|
parent_code TEXT, -- "sf" — родительский жанр
|
||||||
|
root_code TEXT, -- "sf" — корневой жанр
|
||||||
|
is_root BOOLEAN DEFAULT FALSE, -- TRUE для корневых
|
||||||
|
is_custom BOOLEAN DEFAULT FALSE, -- TRUE если добавлен из inpx
|
||||||
|
genre_alt TEXT[], -- альтернативные коды
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Книги
|
||||||
|
CREATE TABLE IF NOT EXISTS books (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
title TEXT NOT NULL,
|
||||||
|
title_hash TEXT, -- MD5 от title (lowercase)
|
||||||
|
internal_id INTEGER, -- ID книги в источнике (LIBID)
|
||||||
|
internal_id2 INTEGER, -- Дублирующий ID
|
||||||
|
file_size INTEGER,
|
||||||
|
format TEXT DEFAULT 'fb2',
|
||||||
|
added_date DATE, -- Дата добавления в источник
|
||||||
|
language TEXT DEFAULT 'ru',
|
||||||
|
source TEXT NOT NULL, -- 'lib.rus.ec', 'flibusta' и т.д.
|
||||||
|
series_id INTEGER REFERENCES series(id) ON DELETE SET NULL,
|
||||||
|
series_number NUMERIC(10,2), -- Номер в серии
|
||||||
|
fts tsvector GENERATED ALWAYS AS (
|
||||||
|
to_tsvector('russian', coalesce(title,''))
|
||||||
|
) STORED,
|
||||||
|
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Связь книг и авторов (многие-ко-многим)
|
||||||
|
CREATE TABLE IF NOT EXISTS book_authors (
|
||||||
|
book_id INTEGER REFERENCES books(id) ON DELETE CASCADE,
|
||||||
|
author_id INTEGER REFERENCES authors(id) ON DELETE CASCADE,
|
||||||
|
position INTEGER, -- Порядок автора (1 = главный)
|
||||||
|
PRIMARY KEY (book_id, author_id)
|
||||||
|
);
|
||||||
|
|
||||||
|
-- Связь книг и жанров (многие-ко-многим)
|
||||||
|
CREATE TABLE IF NOT EXISTS book_genres (
|
||||||
|
book_id INTEGER REFERENCES books(id) ON DELETE CASCADE,
|
||||||
|
genre_id INTEGER REFERENCES genres(id) ON DELETE CASCADE,
|
||||||
|
PRIMARY KEY (book_id, genre_id)
|
||||||
|
);
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
-- ============================================================
|
||||||
|
-- Индексы для быстрого поиска
|
||||||
|
-- ============================================================
|
||||||
|
|
||||||
|
-- Авторы
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_authors_last_name ON authors(last_name);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_authors_first_letter ON authors(first_letter);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_authors_name_hash ON authors(name_hash);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_authors_full_name ON authors(full_name);
|
||||||
|
|
||||||
|
-- Серии
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_series_name_hash ON series(name_hash);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_series_first_letter ON series(first_letter);
|
||||||
|
|
||||||
|
-- Жанры
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_genres_code ON genres(code);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_genres_parent ON genres(parent_code);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_genres_root ON genres(root_code);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_genres_is_root ON genres(is_root);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_genres_is_custom ON genres(is_custom);
|
||||||
|
|
||||||
|
-- Книги
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_books_title_hash ON books(title_hash);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_books_internal_id ON books(internal_id);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_books_internal_id2 ON books(internal_id2);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_books_source ON books(source);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_books_series ON books(series_id, series_number);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_books_language ON books(language);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_books_added_date ON books(added_date DESC NULLS LAST);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_books_fts ON books USING GIN (fts);
|
||||||
|
|
||||||
|
-- Связи
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_book_authors_book ON book_authors(book_id);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_book_authors_author ON book_authors(author_id);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_book_genres_book ON book_genres(book_id);
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_book_genres_genre ON book_genres(genre_id);
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
# SQL-схема Домашней библиотеки
|
||||||
|
|
||||||
|
## Порядок применения
|
||||||
|
|
||||||
|
1. `01_create_tables.sql` — создаёт все таблицы
|
||||||
|
2. `02_create_indexes.sql` — создаёт индексы
|
||||||
|
3. `parse_genres.py` — загружает справочник жанров из `genres.xml`
|
||||||
|
|
||||||
|
## Быстрый запуск
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Через Docker
|
||||||
|
docker compose exec opds bash /app/scripts/init_db.sh
|
||||||
|
|
||||||
|
# Или вручную
|
||||||
|
psql "dbname=books user=postgres password=Karabas@Barabas host=172.20.0.4" \
|
||||||
|
-f sql/01_create_tables.sql \
|
||||||
|
-f sql/02_create_indexes.sql
|
||||||
|
|
||||||
Reference in new issue
Block a user