This repository has been archived on 2026-05-19. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
obsidian/金山办公作业/Week05/数据库设计.md
T
2026-04-20 22:47:51 +08:00

198 lines
7.2 KiB
Markdown
Raw 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.
# 数据库设计文档
## 一、数据库概览
| 项目 | 说明 |
|------|------|
| 数据库名称 | `wordbook` |
| 字符集 | `utf8mb4` |
| 排序规则 | `utf8mb4_unicode_ci` |
| 存储引擎 | `InnoDB` |
## 二、ER 图
```mermaid
erDiagram
USER ||--|{ WORD : has
USER {
uuid id PK "用户ID"
string username UK "用户名"
string password "密码(hash)"
datetime created_at "创建时间"
datetime updated_at "更新时间"
datetime deleted_at "删除时间(软删除)"
}
WORD {
uuid id PK "单词记录ID"
uuid user_id FK "所属用户ID"
string word "单词"
text definition "释义"
json examples "例句列表"
string ai_provider "AI模型来源"
datetime created_at "创建时间"
datetime updated_at "更新时间"
datetime deleted_at "删除时间(软删除)"
}
```
## 三、数据表详情
### 3.1 用户表 (users)
| 用户表名 | `users` |
|----------|---------|
| 字段名 | 数据类型 | 约束 | 索引 | 说明 |
|--------|----------|------|------|------|
| `id` | CHAR(36) | PRIMARY KEY | - | 用户唯一标识符(UUID 格式) |
| `username` | VARCHAR(50) | NOT NULL, UNIQUE | UNIQUE KEY | 用户名,全局唯一,用于登录 |
| `password` | VARCHAR(255) | NOT NULL | - | 用户密码,存储 bcrypt 哈希值,严禁明文存储 |
| `created_at` | DATETIME | DEFAULT CURRENT_TIMESTAMP | - | 账户创建时间 |
| `updated_at` | DATETIME | ON UPDATE CURRENT_TIMESTAMP | - | 账户最后更新时间 |
| `deleted_at` | DATETIME | DEFAULT NULL | INDEX | 软删除标记,NULL 表示未删除 |
**索引设计:**
- 主键索引:`id`
- 唯一索引:`username`(防止重复注册)
### 3.2 单词记录表 (words)
| 单词表名 | `words` |
|-----------|---------|
| 字段名 | 数据类型 | 约束 | 索引 | 说明 |
| ------------- | ------------ | --------------------------- | ------------------------- | ------------------------------------------ |
| `id` | CHAR(36) | PRIMARY KEY | - | 单词记录唯一标识符(UUID 格式) |
| `user_id` | CHAR(36) | NOT NULL, FOREIGN KEY | - | 所属用户 ID,关联 users.id |
| `word` | VARCHAR(100) | NOT NULL | INDEX idx_word_search(20) | 单词文本,支持前缀搜索优化 |
| `definition` | TEXT | NOT NULL | - | AI 生成的单词释义 |
| `examples` | JSON | NOT NULL | - | 例句列表,存储 JSON 数组格式 |
| `ai_provider` | ENUM | NOT NULL | - | AI 模型来源标识(`deepseek`=DeepSeek,`qwen`=通义千问) |
| `created_at` | DATETIME | DEFAULT CURRENT_TIMESTAMP | - | 单词记录创建时间 |
| `updated_at` | DATETIME | ON UPDATE CURRENT_TIMESTAMP | - | 单词记录最后更新时间 |
| `deleted_at` | DATETIME | DEFAULT NULL | INDEX idx_user_word | 软删除标记 |
**索引设计:**
- 主键索引:`id`
- 外键索引:`user_id`(自动创建)
- 唯一索引:`uk_user_word` (user_id, word(50)) - 防止同一用户保存重复单词
- 复合索引:`idx_user_word` (user_id, deleted_at) - 优化用户单词列表分页查询
- 前缀索引:`idx_word_search` (word(20)) - 支持单词前缀搜索优化
## 四、表关联关系
### 4.1 用户与单词的关系
```
用户 (users) 1 ---- N 单词记录 (words)
```
- **关系类型**:一对多
- **外键约束**:`words.user_id` → `users.id`
- **级联规则**:`ON DELETE CASCADE`
- 当用户被删除时,该用户的所有单词记录也会被自动删除
### 4.2 关联查询示例
```sql
-- 查询某用户的所有单词(排除已删除)
SELECT * FROM words
WHERE user_id = ? AND deleted_at IS NULL
ORDER BY created_at DESC
LIMIT ? OFFSET ?;
-- 联表查询用户信息及单词数量
SELECT u.id, u.username, COUNT(w.id) as word_count
FROM users u
LEFT JOIN words w ON u.id = w.user_id AND w.deleted_at IS NULL
WHERE u.deleted_at IS NULL
GROUP BY u.id;
```
### 4.2 唯一约束说明
`uk_user_word` 约束确保同一用户不能保存相同的单词两次:
- **触发场景**:在"手动保存单词"时
- **业务逻辑**:前端应先调用"智能查询单词"接口检查是否已保存,避免触发重复错误
- **不触发场景**:"智能查询单词"接口只查询不保存,不会触发此约束
## 五、核心业务 SQL 查询示例
### 5.1 智能查询单词
**业务逻辑**:先检查数据库,未命中则调用 AI(不保存)
```sql
-- 查询:检查用户是否已保存该单词
SELECT id, word, definition, examples, ai_provider
FROM words
WHERE user_id = ? AND word = ? AND deleted_at IS NULL;
```
### 5.2 手动保存单词
**业务逻辑**:将 AI 返回的结果写入数据库
```sql
-- 插入:保存单词记录(受 uk_user_word 唯一约束保护)
INSERT INTO words (id, user_id, word, definition, examples, ai_provider)
VALUES (?, ?, ?, ?, ?, ?);
```
### 5.3 获取单词列表(分页)
**业务逻辑**:获取用户所有已保存的单词,支持分页
```sql
-- 查询:分页获取单词列表(按创建时间倒序)
SELECT id, word, definition, examples, ai_provider, created_at
FROM words
WHERE user_id = ? AND deleted_at IS NULL
ORDER BY created_at DESC
LIMIT ? OFFSET ?;
-- 计算总数(用于分页器)
SELECT COUNT(*) as total
FROM words
WHERE user_id = ? AND deleted_at IS NULL;
```
### 5.4 删除单词(软删除)
**业务逻辑**:根据单词 ID 软删除记录
```sql
-- 更新:软删除单词记录
UPDATE words
SET deleted_at = CURRENT_TIMESTAMP, updated_at = CURRENT_TIMESTAMP
WHERE id = ? AND user_id = ? AND deleted_at IS NULL;
```
## 六、索引优化说明
### 6.1 查询场景分析
| 查询场景 | 涉及字段 | 索引策略 |
|----------|----------|----------|
| 用户登录 | username | UNIQUE KEY |
| 智能查询单词 | user_id, word, deleted_at | uk_user_word(唯一约束) |
| 用户单词列表(分页) | user_id, deleted_at | 复合索引 idx_user_word |
| 单词搜索 | word | 前缀索引 idx_word_search |
| 按用户 ID 查找单词 | user_id | 外键自动索引 |
### 6.2 示例 JSON 数据结构 (examples 字段)
```json
[
"The word 'serendipity' means finding something good without looking for it.",
"It was pure serendipity that I met my best friend at the coffee shop.",
"Many scientific discoveries are the result of serendipity."
]
```
## 七、数据初始化
数据库初始化脚本位于 `docs/init.sql`,该脚本会在 Docker Compose 启动 MySQL 容器时自动执行。
**严禁使用 GORM 的 `AutoMigrate` 功能进行建表,必须通过此 SQL 脚本初始化数据库。**