diff --git a/schema.sql b/schema.sql index 0be59ca..1b3fc4a 100644 --- a/schema.sql +++ b/schema.sql @@ -3,8 +3,156 @@ -- Поддерживает личные, глобальные и комнатные документы, -- а также историю диалогов (личных и групповых). -- Используется единой базой данных для всех ботов. +-- =================-- ============================================================ +-- schema.sql – схема базы данных PostgreSQL для RAG-сервера +-- Добавлена поддержка флага indexed для транзакционности индексации -- ============================================================ +-- ------------------------------------------------------------------ +-- 1. Таблица documents (метаданные загруженных документов) +-- ------------------------------------------------------------------ +CREATE TABLE IF NOT EXISTS documents ( + id SERIAL PRIMARY KEY, + source_name VARCHAR(255) NOT NULL, + upload_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + owner_jid VARCHAR(255) NOT NULL, + is_global BOOLEAN DEFAULT FALSE, + metadata JSONB, -- PostgreSQL JSONB + room_jid VARCHAR(255) DEFAULT NULL, -- NULL – личный/глобальный; иначе JID комнаты + file_hash VARCHAR(64) DEFAULT NULL, -- SHA-256 хеш содержимого (для обновления версий) + indexed BOOLEAN DEFAULT FALSE -- TRUE, если чанки успешно загружены в Qdrant +); + +-- Индексы для ускорения запросов +CREATE INDEX IF NOT EXISTS idx_documents_owner ON documents(owner_jid); +CREATE INDEX IF NOT EXISTS idx_documents_global ON documents(is_global); +CREATE INDEX IF NOT EXISTS idx_documents_room ON documents(room_jid); +CREATE INDEX IF NOT EXISTS idx_documents_indexed ON documents(indexed); -- новый индекс + +-- Полнотекстовый индекс (GIN) для source_name (русский язык) +CREATE INDEX IF NOT EXISTS ft_source_name ON documents USING GIN (to_tsvector('russian', source_name)); + +-- ------------------------------------------------------------------ +-- 2. Таблица document_access (права доступа к личным документам) +-- ------------------------------------------------------------------ +CREATE TABLE IF NOT EXISTS document_access ( + doc_id INT, + user_jid VARCHAR(255), + PRIMARY KEY (doc_id, user_jid) +); + +CREATE INDEX IF NOT EXISTS idx_access_user ON document_access(user_jid); + +-- ------------------------------------------------------------------ +-- 3. Таблица history (история диалогов) +-- ------------------------------------------------------------------ +DO $$ BEGIN + CREATE TYPE history_role AS ENUM ('user', 'assistant'); +EXCEPTION + WHEN duplicate_object THEN NULL; +END $$; + +CREATE TABLE IF NOT EXISTS history ( + id SERIAL PRIMARY KEY, + user_jid VARCHAR(255) NOT NULL, + role history_role NOT NULL, + content TEXT, + timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + room_jid VARCHAR(255) DEFAULT NULL -- NULL – личный диалог; иначе JID комнаты +); + +CREATE INDEX IF NOT EXISTS idx_history_user ON history(user_jid); +CREATE INDEX IF NOT EXISTS idx_history_room ON history(room_jid); +CREATE INDEX IF NOT EXISTS idx_history_time ON history(timestamp); + +-- ------------------------------------------------------------------ +-- 4. Таблица rooms (список MUC комнат, в которых бот должен состоять) +-- ------------------------------------------------------------------ +CREATE TABLE IF NOT EXISTS rooms ( + room_jid VARCHAR(255) PRIMARY KEY +); + +-- ------------------------------------------------------------------ +-- 5. Таблица room_templates (шаблоны коробочных решений, сохранённые в комнатах) +-- ------------------------------------------------------------------ +CREATE TABLE IF NOT EXISTS room_templates ( + room_jid VARCHAR(255) NOT NULL, + name VARCHAR(255) NOT NULL, + file_path TEXT NOT NULL, + file_hash VARCHAR(64), + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + PRIMARY KEY (room_jid, name) +); + +-- ------------------------------------------------------------------ +-- 6. Таблица feedback (оценки пользователей) – для будущего сбора обратной связи +-- ------------------------------------------------------------------ +CREATE TABLE IF NOT EXISTS feedback ( + id SERIAL PRIMARY KEY, + user_jid VARCHAR(255) NOT NULL, + rating VARCHAR(50) NOT NULL, + comment TEXT, + room_jid VARCHAR(255) DEFAULT NULL, + timestamp TIMESTAMP DEFAULT CURRENT_TIMESTAMP +); + +CREATE INDEX IF NOT EXISTS idx_feedback_user ON feedback(user_jid); + +-- ============================================================ +-- Миграции (если переезжаете с предыдущей версии) +-- ============================================================ + +-- Добавление колонки room_jid в documents (если отсутствует) +DO $$ +BEGIN + IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name='documents' AND column_name='room_jid') THEN + ALTER TABLE documents ADD COLUMN room_jid VARCHAR(255) DEFAULT NULL; + END IF; +END $$; + +-- Добавление колонки file_hash в documents +DO $$ +BEGIN + IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name='documents' AND column_name='file_hash') THEN + ALTER TABLE documents ADD COLUMN file_hash VARCHAR(64) DEFAULT NULL; + END IF; +END $$; + +-- Добавление колонки room_jid в history +DO $$ +BEGIN + IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name='history' AND column_name='room_jid') THEN + ALTER TABLE history ADD COLUMN room_jid VARCHAR(255) DEFAULT NULL; + END IF; +END $$; + +-- Добавление колонки indexed (новое) +DO $$ +BEGIN + IF NOT EXISTS (SELECT 1 FROM information_schema.columns WHERE table_name='documents' AND column_name='indexed') THEN + ALTER TABLE documents ADD COLUMN indexed BOOLEAN DEFAULT FALSE; + -- Для существующих документов считаем, что они уже проиндексированы + UPDATE documents SET indexed = TRUE; + -- Создаём индекс + CREATE INDEX IF NOT EXISTS idx_documents_indexed ON documents(indexed); + END IF; +END $$; + +-- Создание индексов (если отсутствуют) +DO $$ +BEGIN + IF NOT EXISTS (SELECT 1 FROM pg_indexes WHERE indexname='idx_documents_room') THEN + CREATE INDEX idx_documents_room ON documents(room_jid); + END IF; +END $$; + +DO $$ +BEGIN + IF NOT EXISTS (SELECT 1 FROM pg_indexes WHERE indexname='idx_history_room') THEN + CREATE INDEX idx_history_room ON history(room_jid); + END IF; +END $$;=========================================== + -- ------------------------------------------------------------------ -- 1. Таблица documents (метаданные загруженных документов) -- ------------------------------------------------------------------