-- ============================================================ -- EduBrain 数据库初始化脚本 -- 包含 pgvector 扩展、zhparser 中文分词扩展 -- ============================================================ -- 创建 pgvector 扩展(向量相似度搜索) CREATE EXTENSION IF NOT EXISTS vector; -- 创建 zhparser 中文分词扩展(全文搜索) CREATE EXTENSION IF NOT EXISTS zhparser; -- 创建基于 zhparser 的中文全文搜索配置 CREATE TEXT SEARCH CONFIGURATION chinese_zh (PARSER = zhparser); -- 配置中文全文搜索映射:名词、动词、形容词、成语、叹词、习语使用 simple 字典 ALTER TEXT SEARCH CONFIGURATION chinese_zh ADD MAPPING FOR n,v,a,i,e,l WITH simple; -- ============================================================ -- 知识页面表 -- ============================================================ CREATE TABLE IF NOT EXISTS knowledge_pages ( id SERIAL PRIMARY KEY, title VARCHAR(500) NOT NULL, content TEXT NOT NULL, source_file VARCHAR(500), course_name VARCHAR(200), teacher_name VARCHAR(100), live_date VARCHAR(20), page_number INTEGER, metadata_json TEXT, created_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW() ); -- 索引 CREATE INDEX IF NOT EXISTS idx_pages_course ON knowledge_pages(course_name); CREATE INDEX IF NOT EXISTS idx_pages_teacher ON knowledge_pages(teacher_name); CREATE INDEX IF NOT EXISTS idx_pages_date ON knowledge_pages(live_date); CREATE INDEX IF NOT EXISTS idx_pages_created ON knowledge_pages(created_at DESC); -- ============================================================ -- 知识分块表(向量检索单元) -- ============================================================ CREATE TABLE IF NOT EXISTS knowledge_chunks ( id SERIAL PRIMARY KEY, page_id INTEGER NOT NULL REFERENCES knowledge_pages(id) ON DELETE CASCADE, chunk_index INTEGER NOT NULL, content TEXT NOT NULL, embedding vector(1024), -- 嵌入向量(默认 1024 维) search_vector TSVECTOR, -- 中文全文搜索向量 created_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW() ); -- 索引 CREATE INDEX IF NOT EXISTS idx_chunks_page ON knowledge_chunks(page_id); CREATE INDEX IF NOT EXISTS idx_chunks_page_index ON knowledge_chunks(page_id, chunk_index); -- HNSW 向量索引(适合高维向量,查询速度快) CREATE INDEX IF NOT EXISTS idx_chunks_embedding ON knowledge_chunks USING hnsw (embedding vector_cosine_ops) WITH (m = 16, ef_construction = 200); -- GIN 全文搜索索引 CREATE INDEX IF NOT EXISTS idx_chunks_search ON knowledge_chunks USING gin(search_vector); -- ============================================================ -- OCR 图片记录表 -- ============================================================ CREATE TABLE IF NOT EXISTS ocr_images ( id SERIAL PRIMARY KEY, file_path VARCHAR(500) NOT NULL, ocr_text TEXT, confidence FLOAT, provider VARCHAR(50), status VARCHAR(20) DEFAULT 'pending', error_message TEXT, created_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW() ); -- 索引 CREATE INDEX IF NOT EXISTS idx_ocr_status ON ocr_images(status); CREATE INDEX IF NOT EXISTS idx_ocr_created ON ocr_images(created_at DESC); -- ============================================================ -- updated_at 自动更新触发器 -- ============================================================ CREATE OR REPLACE FUNCTION update_updated_at_column() RETURNS TRIGGER AS $$ BEGIN NEW.updated_at = NOW(); RETURN NEW; END; $$ LANGUAGE plpgsql; -- 为所有表添加 updated_at 触发器 DO $$ BEGIN IF NOT EXISTS ( SELECT 1 FROM pg_trigger WHERE tgname = 'tr_pages_updated_at' ) THEN CREATE TRIGGER tr_pages_updated_at BEFORE UPDATE ON knowledge_pages FOR EACH ROW EXECUTE FUNCTION update_updated_at_column(); END IF; IF NOT EXISTS ( SELECT 1 FROM pg_trigger WHERE tgname = 'tr_chunks_updated_at' ) THEN CREATE TRIGGER tr_chunks_updated_at BEFORE UPDATE ON knowledge_chunks FOR EACH ROW EXECUTE FUNCTION update_updated_at_column(); END IF; IF NOT EXISTS ( SELECT 1 FROM pg_trigger WHERE tgname = 'tr_ocr_updated_at' ) THEN CREATE TRIGGER tr_ocr_updated_at BEFORE UPDATE ON ocr_images FOR EACH ROW EXECUTE FUNCTION update_updated_at_column(); END IF; END $$;