note/知识图谱/教科书-数学/all/database_schema.sql
2025-11-19 10:16:05 +08:00

489 lines
16 KiB
PL/PgSQL
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

-- 高中数学知识图谱数据库架构
-- 基于三层架构设计Knowledge知识层、Method方法层、Problem题目层
-- 创建数据库(如果需要)
-- CREATE DATABASE math_knowledge_graph;
-- \c math_knowledge_graph;
-- 启用必要的扩展
CREATE EXTENSION IF NOT EXISTS "uuid-ossp";
CREATE EXTENSION IF NOT EXISTS "pg_trgm";
-- ===========================================
-- 1. 元数据表(教材信息)
-- ===========================================
-- 教材表
CREATE TABLE textbooks (
id SERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL,
publisher VARCHAR(50) DEFAULT '人教版',
version VARCHAR(20) DEFAULT 'A版',
volume_type VARCHAR(20) CHECK (volume_type IN ('必修', '选择性必修')),
volume_number INTEGER,
description TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- 章节表
CREATE TABLE chapters (
id SERIAL PRIMARY KEY,
textbook_id INTEGER REFERENCES textbooks(id) ON DELETE CASCADE,
chapter_number INTEGER NOT NULL,
chapter_name VARCHAR(100) NOT NULL,
chapter_order INTEGER NOT NULL,
description TEXT,
page_range VARCHAR(20),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
UNIQUE(textbook_id, chapter_number)
);
-- 小节表
CREATE TABLE sections (
id SERIAL PRIMARY KEY,
chapter_id INTEGER REFERENCES chapters(id) ON DELETE CASCADE,
section_number VARCHAR(10) NOT NULL,
section_name VARCHAR(100) NOT NULL,
section_order INTEGER NOT NULL,
page_start INTEGER,
page_end INTEGER,
description TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
UNIQUE(chapter_id, section_number)
);
-- ===========================================
-- 2. 知识层Knowledge Layer
-- ===========================================
-- 知识点主表
CREATE TABLE knowledge_points (
id SERIAL PRIMARY KEY,
code VARCHAR(20) UNIQUE NOT NULL, -- 如 K1-1-1-01
name VARCHAR(100) NOT NULL,
level VARCHAR(10) CHECK (level IN ('二级', '三级')),
type VARCHAR(20) CHECK (type IN ('概念/定义', '定理/性质', '公式')),
importance VARCHAR(10) CHECK (importance IN ('核心', '重要', '基础')),
section_id INTEGER REFERENCES sections(id),
-- 核心内容JSON格式存储复杂结构
core_content JSONB,
-- 原理说明
principle_explanation JSONB,
-- 适用条件
application_conditions JSONB,
-- 关联内容
related_content JSONB,
-- 考查方式
examination_methods TEXT[],
-- 教材位置
textbook_location VARCHAR(100),
-- 创建和更新时间
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- 知识点关系表
CREATE TABLE knowledge_relations (
id SERIAL PRIMARY KEY,
source_knowledge_id INTEGER REFERENCES knowledge_points(id) ON DELETE CASCADE,
target_knowledge_id INTEGER REFERENCES knowledge_points(id) ON DELETE CASCADE,
relation_type VARCHAR(20) CHECK (relation_type IN ('前置知识', '包含关系', '关联内容')),
strength FLOAT DEFAULT 1.0 CHECK (strength >= 0 AND strength <= 1),
description TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
UNIQUE(source_knowledge_id, target_knowledge_id, relation_type)
);
-- ===========================================
-- 3. 方法层Method Layer
-- ===========================================
-- 解题方法主表
CREATE TABLE methods (
id SERIAL PRIMARY KEY,
code VARCHAR(20) UNIQUE NOT NULL, -- 如 M1-1-1-01
name VARCHAR(100) NOT NULL,
type VARCHAR(20) CHECK (type IN ('解题方法', '计算技巧', '证明方法')),
difficulty_level INTEGER CHECK (difficulty_level >= 1 AND difficulty_level <= 5),
section_id INTEGER REFERENCES sections(id),
-- 适用场景
application_scenarios JSONB,
-- 数学思想
mathematical_thoughts TEXT[],
-- 解题策略
problem_solving_strategy TEXT,
-- 教材位置
textbook_location VARCHAR(100),
-- 描述
description TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- 方法步骤表
CREATE TABLE method_steps (
id SERIAL PRIMARY KEY,
method_id INTEGER REFERENCES methods(id) ON DELETE CASCADE,
step_number INTEGER NOT NULL,
step_description TEXT NOT NULL,
key_points TEXT[],
common_mistakes TEXT[],
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
UNIQUE(method_id, step_number)
);
-- 方法常见错误表
CREATE TABLE method_common_errors (
id SERIAL PRIMARY KEY,
method_id INTEGER REFERENCES methods(id) ON DELETE CASCADE,
error_description TEXT NOT NULL,
cause_analysis TEXT,
correct_approach TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- 方法支撑知识点表
CREATE TABLE method_support_knowledge (
id SERIAL PRIMARY KEY,
method_id INTEGER REFERENCES methods(id) ON DELETE CASCADE,
knowledge_id INTEGER REFERENCES knowledge_points(id) ON DELETE CASCADE,
support_type VARCHAR(20) CHECK (support_type IN ('直接支撑', '间接支撑')),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
UNIQUE(method_id, knowledge_id)
);
-- ===========================================
-- 4. 题目层Problem Layer
-- ===========================================
-- 题目主表
CREATE TABLE problems (
id SERIAL PRIMARY KEY,
code VARCHAR(20) UNIQUE NOT NULL, -- 如 T1-1-1-E01
title TEXT,
problem_type VARCHAR(20) CHECK (problem_type IN ('例题', '练习题', '习题', '思考题')),
-- 来源信息
source_info JSONB,
-- 题目内容
stem TEXT, -- 题干
full_content TEXT, -- 完整题目
images_info JSONB, -- 图片信息
-- 题型分类
problem_category JSONB,
-- 难度评估
difficulty_info JSONB,
-- 教材位置
textbook_location VARCHAR(100),
-- 小题数量
subquestion_count INTEGER DEFAULT 0,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- 小题表
CREATE TABLE problem_subquestions (
id SERIAL PRIMARY KEY,
problem_id INTEGER REFERENCES problems(id) ON DELETE CASCADE,
subquestion_number VARCHAR(10) NOT NULL, -- 如 (1), (2)
content TEXT,
difficulty_level INTEGER CHECK (difficulty_level >= 1 AND difficulty_level <= 5),
solution TEXT,
answer TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
UNIQUE(problem_id, subquestion_number)
);
-- 题目知识点标注表
CREATE TABLE problem_knowledge_tags (
id SERIAL PRIMARY KEY,
problem_id INTEGER REFERENCES problems(id) ON DELETE CASCADE,
subquestion_id INTEGER REFERENCES problem_subquestions(id) ON DELETE CASCADE,
knowledge_id INTEGER REFERENCES knowledge_points(id) ON DELETE CASCADE,
tag_type VARCHAR(20) CHECK (tag_type IN ('主要考查', '辅助涉及')),
weight FLOAT DEFAULT 1.0 CHECK (weight > 0),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
UNIQUE(problem_id, subquestion_id, knowledge_id, tag_type)
);
-- 题目方法标注表
CREATE TABLE problem_method_tags (
id SERIAL PRIMARY KEY,
problem_id INTEGER REFERENCES problems(id) ON DELETE CASCADE,
subquestion_id INTEGER REFERENCES problem_subquestions(id) ON DELETE CASCADE,
method_id INTEGER REFERENCES methods(id) ON DELETE CASCADE,
usage_frequency VARCHAR(20) CHECK (usage_frequency IN ('主要方法', '辅助方法')),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
UNIQUE(problem_id, subquestion_id, method_id)
);
-- ===========================================
-- 5. 学习分析和扩展表
-- ===========================================
-- 学习路径表(为个性化推荐预留)
CREATE TABLE learning_paths (
id SERIAL PRIMARY KEY,
name VARCHAR(100) NOT NULL,
description TEXT,
knowledge_sequence JSONB,
difficulty_progression JSONB,
estimated_hours INTEGER,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- 难度统计表
CREATE TABLE difficulty_stats (
id SERIAL PRIMARY KEY,
stat_type VARCHAR(20) NOT NULL,
reference_type VARCHAR(20) NOT NULL, -- knowledge, method, problem
reference_id INTEGER NOT NULL,
avg_difficulty FLOAT,
difficulty_distribution JSONB,
sample_size INTEGER,
last_updated TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
UNIQUE(stat_type, reference_type, reference_id)
);
-- ===========================================
-- 6. 全文搜索支持
-- ===========================================
-- 创建全文搜索配置(中文支持)
CREATE TEXT SEARCH CONFIGURATION chinese (COPY = simple);
-- 搜索索引更新函数
CREATE OR REPLACE FUNCTION update_search_vectors()
RETURNS TRIGGER AS $$
BEGIN
-- 更新知识点的搜索向量
IF TG_TABLE_NAME = 'knowledge_points' THEN
UPDATE knowledge_points
SET search_vector =
setweight(to_tsvector('chinese', COALESCE(name, '')), 'A') ||
setweight(to_tsvector('chinese', COALESCE(core_content::text, '')), 'B') ||
setweight(to_tsvector('chinese', COALESCE(principle_explanation::text, '')), 'C')
WHERE id = NEW.id;
END IF;
-- 更新方法的搜索向量
IF TG_TABLE_NAME = 'methods' THEN
UPDATE methods
SET search_vector =
setweight(to_tsvector('chinese', COALESCE(name, '')), 'A') ||
setweight(to_tsvector('chinese', COALESCE(problem_solving_strategy, '')), 'B') ||
setweight(to_tsvector('chinese', COALESCE(description, '')), 'C')
WHERE id = NEW.id;
END IF;
-- 更新题目的搜索向量
IF TG_TABLE_NAME = 'problems' THEN
UPDATE problems
SET search_vector =
setweight(to_tsvector('chinese', COALESCE(title, '')), 'A') ||
setweight(to_tsvector('chinese', COALESCE(stem, '')), 'B') ||
setweight(to_tsvector('chinese', COALESCE(full_content, '')), 'C')
WHERE id = NEW.id;
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
-- 为主要表添加搜索向量字段
ALTER TABLE knowledge_points ADD COLUMN search_vector tsvector;
ALTER TABLE methods ADD COLUMN search_vector tsvector;
ALTER TABLE problems ADD COLUMN search_vector tsvector;
-- 创建触发器
CREATE TRIGGER update_knowledge_search_vector
AFTER INSERT OR UPDATE ON knowledge_points
FOR EACH ROW EXECUTE FUNCTION update_search_vectors();
CREATE TRIGGER update_method_search_vector
AFTER INSERT OR UPDATE ON methods
FOR EACH ROW EXECUTE FUNCTION update_search_vectors();
CREATE TRIGGER update_problem_search_vector
AFTER INSERT OR UPDATE ON problems
FOR EACH ROW EXECUTE FUNCTION update_search_vectors();
-- ===========================================
-- 7. 索引创建
-- ===========================================
-- 基础索引
CREATE INDEX idx_knowledge_points_code ON knowledge_points(code);
CREATE INDEX idx_knowledge_points_level ON knowledge_points(level);
CREATE INDEX idx_knowledge_points_type ON knowledge_points(type);
CREATE INDEX idx_knowledge_points_importance ON knowledge_points(importance);
CREATE INDEX idx_knowledge_points_section ON knowledge_points(section_id);
CREATE INDEX idx_methods_code ON methods(code);
CREATE INDEX idx_methods_type ON methods(type);
CREATE INDEX idx_methods_difficulty ON methods(difficulty_level);
CREATE INDEX idx_methods_section ON methods(section_id);
CREATE INDEX idx_problems_code ON problems(code);
CREATE INDEX idx_problems_type ON problems(problem_type);
CREATE INDEX idx_problems_difficulty ON problems((difficulty_info->>'整体难度')::int);
-- JSON字段索引
CREATE INDEX idx_knowledge_points_content ON knowledge_points USING GIN(core_content);
CREATE INDEX idx_methods_scenarios ON methods USING GIN(application_scenarios);
CREATE INDEX idx_problems_source ON problems USING GIN(source_info);
-- 搜索向量索引
CREATE INDEX idx_knowledge_points_search ON knowledge_points USING GIN(search_vector);
CREATE INDEX idx_methods_search ON methods USING GIN(search_vector);
CREATE INDEX idx_problems_search ON problems USING GIN(search_vector);
-- 关系表索引
CREATE INDEX idx_knowledge_relations_source ON knowledge_relations(source_knowledge_id);
CREATE INDEX idx_knowledge_relations_target ON knowledge_relations(target_knowledge_id);
CREATE INDEX idx_knowledge_relations_type ON knowledge_relations(relation_type);
CREATE INDEX idx_problem_knowledge_tags_problem ON problem_knowledge_tags(problem_id);
CREATE INDEX idx_problem_knowledge_tags_knowledge ON problem_knowledge_tags(knowledge_id);
CREATE INDEX idx_problem_method_tags_problem ON problem_method_tags(problem_id);
CREATE INDEX idx_problem_method_tags_method ON problem_method_tags(method_id);
-- ===========================================
-- 8. 约束和触发器
-- ===========================================
-- 更新时间触发器
CREATE OR REPLACE FUNCTION update_updated_at_column()
RETURNS TRIGGER AS $$
BEGIN
NEW.updated_at = CURRENT_TIMESTAMP;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
-- 为需要的表添加更新时间触发器
CREATE TRIGGER update_knowledge_points_updated_at
BEFORE UPDATE ON knowledge_points
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
CREATE TRIGGER update_methods_updated_at
BEFORE UPDATE ON methods
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
CREATE TRIGGER update_problems_updated_at
BEFORE UPDATE ON problems
FOR EACH ROW EXECUTE FUNCTION update_updated_at_column();
-- 检查约束
ALTER TABLE knowledge_points ADD CONSTRAINT chk_knowledge_code_format
CHECK (code ~ '^K\d+-\d+-\d+-\d+$');
ALTER TABLE methods ADD CONSTRAINT chk_method_code_format
CHECK (code ~ '^M\d+-\d+-\d+-\d+$');
ALTER TABLE problems ADD CONSTRAINT chk_problem_code_format
CHECK (code ~ '^T\d+-\d+-\d+-[A-Z]\d+$');
-- ===========================================
-- 9. 初始数据插入
-- ===========================================
-- 插入教材信息示例
INSERT INTO textbooks (name, volume_type, volume_number, description) VALUES
('高中数学必修第一册', '必修', 1, '人教版高中数学必修第一册'),
('高中数学必修第二册', '必修', 2, '人教版高中数学必修第二册'),
('高中数学选择性必修第一册', '选择性必修', 1, '人教版高中数学选择性必修第一册'),
('高中数学选择性必修第二册', '选择性必修', 2, '人教版高中数学选择性必修第二册'),
('高中数学选择性必修第三册', '选择性必修', 3, '人教版高中数学选择性必修第三册');
-- ===========================================
-- 10. 视图创建
-- ===========================================
-- 知识点详细信息视图
CREATE VIEW knowledge_detail_view AS
SELECT
kp.id,
kp.code,
kp.name,
kp.level,
kp.type,
kp.importance,
s.section_name,
c.chapter_name,
t.name as textbook_name,
kp.core_content,
kp.principle_explanation,
kp.examination_methods,
kp.textbook_location,
kp.created_at
FROM knowledge_points kp
LEFT JOIN sections s ON kp.section_id = s.id
LEFT JOIN chapters c ON s.chapter_id = c.id
LEFT JOIN textbooks t ON c.textbook_id = t.id;
-- 题目详细信息视图
CREATE VIEW problem_detail_view AS
SELECT
p.id,
p.code,
p.problem_type,
p.title,
p.stem,
p.full_content,
p.difficulty_info,
s.section_name,
c.chapter_name,
t.name as textbook_name,
p.textbook_location,
p.subquestion_count,
p.created_at
FROM problems p
LEFT JOIN knowledge_points kp ON p.section_id = kp.section_id
LEFT JOIN sections s ON kp.section_id = s.id
LEFT JOIN chapters c ON s.chapter_id = c.id
LEFT JOIN textbooks t ON c.textbook_id = t.id;
-- 方法详细信息视图
CREATE VIEW method_detail_view AS
SELECT
m.id,
m.code,
m.name,
m.type,
m.difficulty_level,
m.mathematical_thoughts,
m.problem_solving_strategy,
s.section_name,
c.chapter_name,
t.name as textbook_name,
m.textbook_location,
m.created_at
FROM methods m
LEFT JOIN sections s ON m.section_id = s.id
LEFT JOIN chapters c ON s.chapter_id = c.id
LEFT JOIN textbooks t ON c.textbook_id = t.id;
COMMENT ON DATABASE math_knowledge_graph IS '高中数学知识图谱数据库';