484 lines
17 KiB
Markdown
484 lines
17 KiB
Markdown
# 字词学习平台 - 数据库设计文档
|
||
|
||
## 1. 数据库选型
|
||
|
||
### 1.1 推荐方案:PostgreSQL
|
||
|
||
**选择理由:**
|
||
- ✅ **关系型数据优势**:字词、关联关系、用户等数据具有强关联性,适合关系型数据库
|
||
- ✅ **JSON 支持**:PostgreSQL 原生支持 JSON/JSONB,可以灵活存储 SVG 数据
|
||
- ✅ **全文搜索**:内置全文搜索功能,适合字词搜索场景
|
||
- ✅ **扩展性强**:支持数组类型,适合存储多个拼音、多个读音等
|
||
- ✅ **成熟稳定**:企业级数据库,性能优秀
|
||
- ✅ **开源免费**:成本可控
|
||
|
||
### 1.2 备选方案
|
||
|
||
**MySQL 8.0+**
|
||
- 优势:生态成熟,使用广泛
|
||
- 劣势:JSON 支持不如 PostgreSQL 完善
|
||
|
||
**MongoDB**
|
||
- 优势:文档型数据库,灵活性强
|
||
- 劣势:关联查询复杂,不适合强关联关系场景
|
||
|
||
## 2. 数据库分离设计
|
||
|
||
### 2.1 核心设计思路
|
||
|
||
**字和词分离为两个独立的数据库**
|
||
|
||
**设计原则:**
|
||
1. ✅ **汉字数据库**:专门存储汉字相关数据,包含汉字的特有属性(笔画、结构、部首等)
|
||
2. ✅ **词语数据库**:专门存储词语相关数据,包含词语的组成和关联关系
|
||
3. ✅ **数据隔离**:字和词的数据结构差异较大,分离后更便于管理和优化
|
||
4. ✅ **扩展性好**:后续如需支持英语单词,可单独设计英语数据库
|
||
|
||
**注意:**
|
||
- 英语展示不考虑和汉字放在一个库
|
||
- 当前版本先完成汉字数据库的设计和实现
|
||
- 词语数据库表暂时设计,后续实现
|
||
|
||
## 3. 汉字数据库设计
|
||
|
||
### 3.1 汉字主表 (chars)
|
||
|
||
存储汉字的基础信息。
|
||
|
||
```sql
|
||
CREATE TABLE chars (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
char VARCHAR(10) NOT NULL UNIQUE COMMENT '汉字内容,如"中"',
|
||
strokes INT NOT NULL COMMENT '笔画数',
|
||
pinyin TEXT[] NOT NULL COMMENT '拼音数组,支持多音字,如["zhōng", "zhòng"]',
|
||
radicals VARCHAR(10) COMMENT '偏旁部首',
|
||
frequency INT COMMENT '使用频率: 0(最常用), 1(较常用), 2(次常用), 3(二级字), 4(三级字), 5(生僻字)',
|
||
structure VARCHAR(10) COMMENT '汉字结构代码,如"D0"(独体结构), "H2"(左窄右宽)等',
|
||
traditional VARCHAR(50) COMMENT '繁体字写法,可能有多个,用逗号分隔',
|
||
stroke_data JSONB COMMENT '笔画数据,JSON格式,存储笔画顺序和路径信息',
|
||
grade INT COMMENT '年级: 0-9,NULL表示未设置',
|
||
description TEXT COMMENT '描述信息',
|
||
status VARCHAR(20) DEFAULT 'active' COMMENT '状态: active(启用), inactive(禁用)',
|
||
|
||
-- 索引
|
||
INDEX idx_char (char),
|
||
INDEX idx_strokes (strokes),
|
||
INDEX idx_pinyin (pinyin),
|
||
INDEX idx_radicals (radicals),
|
||
INDEX idx_frequency (frequency),
|
||
INDEX idx_structure (structure),
|
||
INDEX idx_grade (grade),
|
||
INDEX idx_status (status)
|
||
);
|
||
|
||
-- 全文搜索索引
|
||
CREATE INDEX idx_char_fulltext ON chars USING GIN (to_tsvector('simple', char));
|
||
```
|
||
|
||
**字段说明:**
|
||
- `char`: 汉字内容,唯一不重复,如"中"
|
||
- `strokes`: 笔画数,整数类型
|
||
- `pinyin`: PostgreSQL 数组类型,存储多个拼音,支持多音字
|
||
- `radicals`: 偏旁部首,如"中"的部首是"丨"
|
||
- `frequency`: 使用频率,0为最常用,1为较常用,2为次常用,3为二级字,4为三级字,5为不在《通用规范汉字》的生僻字
|
||
- `structure`: 汉字结构代码,参考结构代码表(见 `structure_codes.json`),如"D0"(独体结构)、"H2"(左窄右宽)等
|
||
- `traditional`: 繁体字写法,可能有多个,用逗号分隔,如"乾幹"
|
||
- `stroke_data`: JSONB 类型,存储笔画数据,包含笔画顺序和路径信息(原 svg_data 字段)
|
||
- `grade`: 年级,0-9年级,NULL 表示未设置
|
||
- `status`: 启用/禁用状态,支持软删除
|
||
|
||
**说明:** 音频文件已迁移至 `char_readings` 表,按音义项分别存储。
|
||
|
||
**结构代码说明:**
|
||
- 结构代码定义见 `structure_codes.json` 文件
|
||
- 常见结构代码:D0(独体结构)、D1(镶嵌结构)、B1-B4(上下结构)、H1-H3(左右结构)、R1-R6(半包围结构)等
|
||
|
||
### 3.2 汉字音义项表 (char_readings)
|
||
|
||
存储每个汉字在不同读音/含义下的信息,支持多音字、多义字。单音字一条记录,多音字/同音多义字多条记录。
|
||
|
||
```sql
|
||
CREATE TABLE char_readings (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
char_id BIGINT NOT NULL,
|
||
pinyin VARCHAR(20) NOT NULL COMMENT '读音,如 zhōng、zhòng',
|
||
meaning VARCHAR(200) COMMENT '义项说明,同音多义时用于区分,如"中间;中心"、"击中;符合"',
|
||
introduce TEXT NOT NULL COMMENT '该音义项下的提示语',
|
||
audio_file_ref VARCHAR(500) COMMENT '音频相对路径,与配置中的 base URL 拼接,如 audio/chars/中/zhōng.mp3',
|
||
image_file_ref VARCHAR(500) COMMENT '图片相对路径,可选,幼小低年级字才有释义图',
|
||
sort_order INT DEFAULT 0 COMMENT '排序,常用音义可放前面',
|
||
|
||
FOREIGN KEY (char_id) REFERENCES chars(id) ON DELETE CASCADE,
|
||
INDEX idx_char_id (char_id),
|
||
INDEX idx_pinyin (pinyin),
|
||
INDEX idx_char_pinyin (char_id, pinyin)
|
||
);
|
||
```
|
||
|
||
**字段说明:**
|
||
- `char_id`: 关联的汉字ID
|
||
- `pinyin`: 该音义项的读音
|
||
- `meaning`: 义项说明,同音多义时用于区分
|
||
- `introduce`: 该音义项下的提示语(如"中,中间的中")
|
||
- `audio_file_ref`: 音频相对路径,采用 relative 方案,与配置中的 base URL 拼接成完整地址
|
||
- `image_file_ref`: 图片相对路径,可选,仅部分字(如幼小低年级需掌握的字)有此字段
|
||
- `sort_order`: 排序,常用音义优先展示
|
||
|
||
**路径约定:**
|
||
- 音频、图片均使用 relative 方案,数据库仅存相对路径
|
||
- base URL 在应用配置中维护,迁移 CDN/域名时无需更新数据库
|
||
- 示例:`audio_file_ref = "audio/chars/中/zhōng.mp3"`,完整地址 = `{base_url}/{audio_file_ref}`
|
||
|
||
### 3.3 汉字图片表 (char_images)
|
||
|
||
存储汉字字形相关图片(原图、标准图等,与读音无关)。
|
||
|
||
```sql
|
||
CREATE TABLE char_images (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
char_id BIGINT NOT NULL COMMENT '关联的汉字ID',
|
||
image_type VARCHAR(20) NOT NULL COMMENT '图片类型: original(原图), standard(标准图)',
|
||
file_path VARCHAR(500) NOT NULL COMMENT '图片文件路径',
|
||
file_name VARCHAR(200) NOT NULL COMMENT '原始文件名',
|
||
file_size BIGINT COMMENT '文件大小(字节)',
|
||
width INT COMMENT '图片宽度',
|
||
height INT COMMENT '图片高度',
|
||
mime_type VARCHAR(50) COMMENT 'MIME类型',
|
||
is_primary BOOLEAN DEFAULT FALSE COMMENT '是否为主图',
|
||
sort_order INT DEFAULT 0 COMMENT '排序顺序',
|
||
|
||
FOREIGN KEY (char_id) REFERENCES chars(id) ON DELETE CASCADE,
|
||
INDEX idx_char_id (char_id),
|
||
INDEX idx_image_type (image_type),
|
||
INDEX idx_is_primary (is_primary)
|
||
);
|
||
```
|
||
|
||
**字段说明:**
|
||
- `char_id`: 关联的汉字ID
|
||
- `image_type`: 区分原图和标准图
|
||
- `file_path`: 图片存储路径
|
||
- `is_primary`: 标记主图,用于列表展示
|
||
- `sort_order`: 排序字段,支持多图排序
|
||
|
||
### 3.4 汉字关联表 (char_relations)
|
||
|
||
存储汉字之间的关联关系(如形近字、同音字等)。
|
||
|
||
```sql
|
||
CREATE TABLE char_relations (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
source_char_id BIGINT NOT NULL COMMENT '源汉字ID',
|
||
target_char_id BIGINT NOT NULL COMMENT '目标汉字ID',
|
||
relation_type VARCHAR(20) NOT NULL COMMENT '关联类型: similar_shape(形近字), same_pinyin(同音字), same_radical(同部首), similar_structure(同结构)',
|
||
sort_order INT DEFAULT 0 COMMENT '排序顺序',
|
||
|
||
FOREIGN KEY (source_char_id) REFERENCES chars(id) ON DELETE CASCADE,
|
||
FOREIGN KEY (target_char_id) REFERENCES chars(id) ON DELETE CASCADE,
|
||
UNIQUE (source_char_id, target_char_id, relation_type),
|
||
INDEX idx_source_char (source_char_id),
|
||
INDEX idx_target_char (target_char_id),
|
||
INDEX idx_relation_type (relation_type)
|
||
);
|
||
```
|
||
|
||
**关联类型说明:**
|
||
- `similar_shape`: 形近字,如"人"和"入"
|
||
- `same_pinyin`: 同音字,如"中"和"钟"
|
||
- `same_radical`: 同部首,如"中"和"串"
|
||
- `similar_structure`: 同结构,如都是左右结构
|
||
|
||
### 3.5 句子表 (sentences)
|
||
|
||
存储字词关联的例句。
|
||
|
||
```sql
|
||
CREATE TABLE sentences (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
content TEXT NOT NULL COMMENT '句子内容',
|
||
translation TEXT COMMENT '翻译(英语句子需要)',
|
||
audio_path VARCHAR(500) COMMENT '音频文件路径',
|
||
source VARCHAR(100) COMMENT '来源,如教材名称',
|
||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||
|
||
INDEX idx_content_fulltext (to_tsvector('simple', content))
|
||
);
|
||
```
|
||
|
||
### 3.6 汉字-句子关联表 (char_sentences)
|
||
|
||
存储汉字和句子的关联关系。
|
||
|
||
```sql
|
||
CREATE TABLE char_sentences (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
char_id BIGINT NOT NULL COMMENT '汉字ID',
|
||
sentence_id BIGINT NOT NULL COMMENT '句子ID',
|
||
sort_order INT DEFAULT 0 COMMENT '排序顺序',
|
||
|
||
FOREIGN KEY (char_id) REFERENCES chars(id) ON DELETE CASCADE,
|
||
FOREIGN KEY (sentence_id) REFERENCES sentences(id) ON DELETE CASCADE,
|
||
UNIQUE (char_id, sentence_id),
|
||
INDEX idx_char_id (char_id),
|
||
INDEX idx_sentence_id (sentence_id)
|
||
);
|
||
```
|
||
|
||
### 3.7 用户表 (users)
|
||
|
||
存储管理员用户信息。
|
||
|
||
```sql
|
||
CREATE TABLE users (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
username VARCHAR(50) NOT NULL UNIQUE COMMENT '用户名',
|
||
email VARCHAR(100) UNIQUE COMMENT '邮箱',
|
||
password_hash VARCHAR(255) NOT NULL COMMENT '密码哈希',
|
||
role VARCHAR(20) NOT NULL DEFAULT 'admin' COMMENT '角色: super_admin(超级管理员), admin(一般管理员)',
|
||
real_name VARCHAR(50) COMMENT '真实姓名',
|
||
avatar VARCHAR(500) COMMENT '头像URL',
|
||
status VARCHAR(20) DEFAULT 'active' COMMENT '状态: active(启用), inactive(禁用)',
|
||
last_login_at TIMESTAMP COMMENT '最后登录时间',
|
||
last_login_ip VARCHAR(50) COMMENT '最后登录IP',
|
||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||
|
||
INDEX idx_username (username),
|
||
INDEX idx_email (email),
|
||
INDEX idx_role (role),
|
||
INDEX idx_status (status)
|
||
);
|
||
```
|
||
|
||
### 3.8 操作日志表 (operation_logs)
|
||
|
||
记录用户操作日志,用于审计。
|
||
|
||
```sql
|
||
CREATE TABLE operation_logs (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
user_id BIGINT COMMENT '操作用户ID',
|
||
action VARCHAR(50) NOT NULL COMMENT '操作类型: create, update, delete, upload等',
|
||
resource_type VARCHAR(50) NOT NULL COMMENT '资源类型: word, image, sentence等',
|
||
resource_id BIGINT COMMENT '资源ID',
|
||
description TEXT COMMENT '操作描述',
|
||
ip_address VARCHAR(50) COMMENT 'IP地址',
|
||
user_agent TEXT COMMENT '用户代理',
|
||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||
|
||
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL,
|
||
INDEX idx_user_id (user_id),
|
||
INDEX idx_action (action),
|
||
INDEX idx_resource (resource_type, resource_id),
|
||
INDEX idx_created_at (created_at)
|
||
);
|
||
```
|
||
|
||
## 4. 词语数据库设计(暂时设计)
|
||
|
||
### 4.1 词语主表 (chinese_words)
|
||
|
||
存储词语的基础信息。
|
||
|
||
```sql
|
||
CREATE TABLE chinese_words (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
word VARCHAR(100) NOT NULL UNIQUE COMMENT '词语内容,如"中国"',
|
||
pinyin TEXT[] COMMENT '拼音数组,如["zhōng", "guó"]',
|
||
grade INT COMMENT '年级: 0-9,NULL表示未设置',
|
||
description TEXT COMMENT '词语解释',
|
||
audios TEXT[] COMMENT '音频文件路径数组',
|
||
status VARCHAR(20) DEFAULT 'active' COMMENT '状态: active(启用), inactive(禁用)',
|
||
|
||
-- 索引
|
||
INDEX idx_word (word),
|
||
INDEX idx_grade (grade),
|
||
INDEX idx_status (status)
|
||
);
|
||
|
||
-- 全文搜索索引
|
||
CREATE INDEX idx_word_fulltext ON chinese_words USING GIN (to_tsvector('simple', word));
|
||
```
|
||
|
||
### 4.2 词语-汉字关联表 (word_characters)
|
||
|
||
存储词语和组成汉字的关联关系。
|
||
|
||
```sql
|
||
CREATE TABLE word_characters (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
word_id BIGINT NOT NULL COMMENT '词语ID',
|
||
char_id BIGINT NOT NULL COMMENT '汉字ID(关联到汉字数据库)',
|
||
position INT NOT NULL COMMENT '汉字在词语中的位置,从1开始',
|
||
|
||
FOREIGN KEY (word_id) REFERENCES chinese_words(id) ON DELETE CASCADE,
|
||
INDEX idx_word_id (word_id),
|
||
INDEX idx_char_id (char_id),
|
||
INDEX idx_position (position)
|
||
);
|
||
```
|
||
|
||
**注意:** 词语数据库和汉字数据库是分离的,`char_id` 字段存储的是汉字数据库中的汉字ID,需要通过跨库查询或应用层关联。
|
||
|
||
### 4.3 词语图片表 (word_images)
|
||
|
||
存储词语关联的图片信息。
|
||
|
||
```sql
|
||
CREATE TABLE word_images (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
word_id BIGINT NOT NULL COMMENT '关联的词语ID',
|
||
image_type VARCHAR(20) NOT NULL COMMENT '图片类型: original(原图), standard(标准图)',
|
||
file_path VARCHAR(500) NOT NULL COMMENT '图片文件路径',
|
||
file_name VARCHAR(200) NOT NULL COMMENT '原始文件名',
|
||
file_size BIGINT COMMENT '文件大小(字节)',
|
||
width INT COMMENT '图片宽度',
|
||
height INT COMMENT '图片高度',
|
||
mime_type VARCHAR(50) COMMENT 'MIME类型',
|
||
is_primary BOOLEAN DEFAULT FALSE COMMENT '是否为主图',
|
||
sort_order INT DEFAULT 0 COMMENT '排序顺序',
|
||
|
||
FOREIGN KEY (word_id) REFERENCES chinese_words(id) ON DELETE CASCADE,
|
||
INDEX idx_word_id (word_id),
|
||
INDEX idx_image_type (image_type),
|
||
INDEX idx_is_primary (is_primary)
|
||
);
|
||
```
|
||
|
||
### 4.4 词语-句子关联表 (word_sentences)
|
||
|
||
存储词语和句子的关联关系。
|
||
|
||
```sql
|
||
CREATE TABLE word_sentences (
|
||
id BIGSERIAL PRIMARY KEY,
|
||
word_id BIGINT NOT NULL COMMENT '词语ID',
|
||
sentence_id BIGINT NOT NULL COMMENT '句子ID',
|
||
sort_order INT DEFAULT 0 COMMENT '排序顺序',
|
||
|
||
FOREIGN KEY (word_id) REFERENCES chinese_words(id) ON DELETE CASCADE,
|
||
FOREIGN KEY (sentence_id) REFERENCES sentences(id) ON DELETE CASCADE,
|
||
UNIQUE (word_id, sentence_id),
|
||
INDEX idx_word_id (word_id),
|
||
INDEX idx_sentence_id (sentence_id)
|
||
);
|
||
```
|
||
|
||
## 5. 数据库关系图
|
||
|
||
### 5.1 汉字数据库关系图
|
||
|
||
```
|
||
chars (汉字主表)
|
||
├── char_readings (音义项表) - 一对多,支持多音字、多义字
|
||
├── char_images (字形图片表) - 一对多
|
||
├── char_relations (汉字关联) - 自关联(多对多)
|
||
├── char_sentences (汉字-句子关联) - 多对多
|
||
└── operation_logs (操作日志) - 关联资源
|
||
|
||
char_readings (音义项表)
|
||
└── 存储 introduce、audio_file_ref、image_file_ref 等按读音/义项区分的数据
|
||
|
||
sentences (句子表)
|
||
└── char_sentences (汉字-句子关联) - 多对多
|
||
```
|
||
|
||
### 5.2 词语数据库关系图
|
||
|
||
```
|
||
chinese_words (词语主表)
|
||
├── word_characters (词语-汉字关联) - 多对多(跨库关联)
|
||
├── word_images (图片表) - 一对多
|
||
├── word_sentences (词语-句子关联) - 多对多
|
||
└── operation_logs (操作日志) - 关联资源
|
||
|
||
sentences (句子表)
|
||
└── word_sentences (词语-句子关联) - 多对多
|
||
```
|
||
|
||
### 5.3 公共表
|
||
|
||
```
|
||
users (用户表)
|
||
└── operation_logs (操作日志) - 一对多
|
||
|
||
sentences (句子表)
|
||
├── char_sentences (汉字-句子关联) - 多对多
|
||
└── word_sentences (词语-句子关联) - 多对多
|
||
```
|
||
|
||
## 6. 索引优化建议
|
||
|
||
### 6.1 汉字数据库查询优化索引
|
||
- 汉字内容索引:支持快速查找
|
||
- 笔画数索引:支持按笔画数筛选
|
||
- 拼音索引:支持按拼音查找
|
||
- 部首索引:支持按部首查找
|
||
- 结构代码索引:支持按结构筛选
|
||
- 频率索引:支持按使用频率筛选
|
||
- 全文搜索索引:支持模糊搜索
|
||
|
||
### 6.2 词语数据库查询优化索引
|
||
- 词语内容索引:支持快速查找
|
||
- 年级索引:支持按年级筛选
|
||
- 全文搜索索引:支持模糊搜索
|
||
|
||
### 6.3 关联查询优化
|
||
- 外键索引:所有外键字段建立索引
|
||
- 关联表索引:char_readings、char_relations、char_sentences、word_characters、word_sentences 的关联字段索引
|
||
|
||
## 7. 数据迁移策略
|
||
|
||
### 7.1 初始化数据
|
||
- 创建默认超级管理员账户
|
||
- 初始化年级数据字典(可选)
|
||
- 导入汉字结构代码数据(structure_codes.json)
|
||
|
||
### 7.2 数据导入
|
||
- 支持批量导入汉字数据(参考 char_common_base.json 格式)
|
||
- 支持批量导入音义项数据(参考 char_introduce.json,需按多音/多义拆分为多条 char_readings)
|
||
- 支持批量导入词语数据
|
||
- 支持 CSV/Excel 格式导入
|
||
|
||
### 7.3 数据迁移注意事项
|
||
- 从旧的 words 表迁移到 chars 表时,需要:
|
||
- 将 `content` 字段映射到 `char` 字段
|
||
- 将 `svg_data` 字段重命名为 `stroke_data`
|
||
- 补充 `strokes`、`pinyin`、`radicals`、`frequency`、`structure`、`traditional` 字段
|
||
- 过滤出 `type = 'chinese_char'` 的数据
|
||
- 从 char_introduce.json 迁移到 char_readings 时,需要:
|
||
- 单音字:每条 JSON 对应一条 char_readings 记录
|
||
- 多音字/多义字:需人工或脚本标注拆分,每个音义项一条 char_readings 记录
|
||
|
||
## 8. 数据备份策略
|
||
|
||
### 8.1 备份方案
|
||
- 每日全量备份
|
||
- 实时增量备份(可选)
|
||
- 汉字数据库和词语数据库分别备份
|
||
|
||
### 8.2 恢复方案
|
||
- 支持时间点恢复
|
||
- 定期恢复演练
|
||
|
||
## 9. 性能优化建议
|
||
|
||
### 9.1 查询优化
|
||
- 使用连接池管理数据库连接
|
||
- 复杂查询使用视图或物化视图
|
||
- 合理使用缓存(Redis)
|
||
- 跨库查询(词语-汉字关联)建议在应用层实现,避免跨库JOIN
|
||
|
||
### 9.2 数据量预估
|
||
- 汉字数据:预计 8,000+ 条(通用规范汉字表)
|
||
- 音义项数据:预计 10,000~12,000 条(多音字对应多条记录)
|
||
- 词语数据:预计 10,000+ 条
|
||
- 图片数据:预计 50,000+ 条
|
||
- 关联关系:预计 100,000+ 条
|
||
|
||
### 9.3 分表策略(如需要)
|
||
- 当 chars 表数据量超过 100 万时,考虑按频率分表
|
||
- 当 chinese_words 表数据量超过 100 万时,考虑按年级分表
|
||
- 使用 PostgreSQL 分区功能
|