- 流式查询(SSE 实时展示生成过程) - 三维度数据模型:history(查询)/ words(单词档案)/ roots(词根档案) - 词根拆解与发音拼读训练(词根点击揭晓历史词例) - 词义/同义例句跨查询累积,同义项自动合并 - 历史与词库分页、多维度搜索 - 模型:Qwen3.6-35B-A3B(硅基流动,可 LLM_MODEL 切换)
174 lines
6.5 KiB
Markdown
174 lines
6.5 KiB
Markdown
# 数据库表结构文档
|
||
|
||
> 数据库:SQLite(`data/app.db`,WAL 模式)
|
||
> 最后更新:2026-08-28(词根维度 + 搜索功能版本)
|
||
> 表结构维护方式:启动时 `CREATE TABLE IF NOT EXISTS` 自动建表 + 代码内增量迁移(`ALTER TABLE`),无需手工执行 SQL
|
||
|
||
## 总览
|
||
|
||
系统按三个维度存储学习数据:
|
||
|
||
| 表 | 维度 | 说明 |
|
||
|---|---|---|
|
||
| `history` | 查询次数 | 每次查询的原句与完整结果快照 |
|
||
| `words` | 单词 | 跨查询累积的单词档案(释义、词根拆解、原句记录) |
|
||
| `roots` | 词根 | 跨单词累积的词根档案(哪些学过的词包含它、各词中体现的含义) |
|
||
|
||
### 维度间关系
|
||
|
||
```
|
||
history (一次查询)
|
||
│ 查询完成后自动触发
|
||
▼
|
||
words (每词一行) ──写入时同步──▶ roots (每词根一行)
|
||
```
|
||
|
||
- `words.word` 唯一;`roots.root`(规范化键)唯一
|
||
- 同一单词在 `roots` 下仅保留一条映射(重新拆解时旧映射自动摘除)
|
||
|
||
---
|
||
|
||
## 1. history — 查询历史(按次记录)
|
||
|
||
| 列 | 类型 | 约束 | 说明 |
|
||
|---|---|---|---|
|
||
| `id` | INTEGER | PK, AUTOINCREMENT | 记录 ID |
|
||
| `sentence` | TEXT | NOT NULL | 用户粘贴的原句 |
|
||
| `words` | TEXT | NOT NULL | 查询的单词列表,JSON 数组:`["analysis", "analyze"]` |
|
||
| `result` | TEXT | NOT NULL | LLM 结构化结果快照,见下方 JSON 结构 |
|
||
| `raw_result` | TEXT | 可空 | LLM 原始输出(排查用) |
|
||
| `created_at` / `updated_at` | TEXT | NOT NULL | 本地时间,写入/最后编辑时间 |
|
||
|
||
### `result` JSON 结构
|
||
|
||
```json
|
||
{
|
||
"sentence_translation": "整个原句的中文翻译",
|
||
"words": [
|
||
{
|
||
"word": "analysis",
|
||
"phonetic": "/əˈnæləsɪs/",
|
||
"roots": [
|
||
{ "part": "ana-", "type": "前缀", "phonetic": "/əˈnæ/", "meaning": "向上、全面" }
|
||
],
|
||
"context_sense_id": 0,
|
||
"context_sense": "n. 分析;解析",
|
||
"context_examples": [
|
||
{ "en": "English sentence.", "zh": "中文翻译" }
|
||
],
|
||
"other_senses": [
|
||
{
|
||
"sense_id": -1,
|
||
"sense": "n. 化验",
|
||
"examples": [ { "en": "...", "zh": "..." } ]
|
||
}
|
||
]
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
- `context_sense_id`:本次语境命中的词库已有释义编号(0 起),`-1` 表示新释义
|
||
- `roots[].type`:前缀 / 词根 / 后缀 / 音节
|
||
- 已编辑的历史记录中 `roots` 支持手工维护(编辑界面按 `部分 | 类型 | 音标 | 含义` 行格式)
|
||
|
||
---
|
||
|
||
## 2. words — 词库(按单词维度,跨查询累积)
|
||
|
||
| 列 | 类型 | 约束 | 说明 |
|
||
|---|---|---|---|
|
||
| `id` | INTEGER | PK, AUTOINCREMENT | |
|
||
| `word` | TEXT | NOT NULL, **UNIQUE**(自动索引) | 单词小写形式 |
|
||
| `phonetic` | TEXT | | 整词美式音标 |
|
||
| `roots` | TEXT | NOT NULL, 默认 `'[]'` | 词根拆解,JSON:`[{part, type, phonetic, meaning}]` |
|
||
| `senses` | TEXT | NOT NULL, 默认 `'[]'` | 释义累积,见下方 |
|
||
| `root_keys` | TEXT | NOT NULL, 默认 `'[]'` | 该词当前映射到的词根规范化键,如 `["ana","naly","sis"]` |
|
||
| `search_text` | TEXT | NOT NULL, 默认 `''` | 检索文本(见下) |
|
||
| `created_at` / `updated_at` | TEXT | NOT NULL | |
|
||
|
||
### `senses` JSON 结构
|
||
|
||
```json
|
||
[
|
||
{
|
||
"sense": "n. 分析;解析",
|
||
"examples": [
|
||
{ "en": "原句本身", "zh": "原句翻译", "from_sentence": true },
|
||
{ "en": "AI 生成的同义例句", "zh": "翻译" }
|
||
]
|
||
}
|
||
]
|
||
```
|
||
|
||
- 同义义项合并规则:新查询语境命中已有义项(`context_sense_id`)→ 追加"原句 + 本次生成的同义例句";新语境 → 新增义项
|
||
- 例句按英文原文去重;`from_sentence: true` 标记来自真实原句(前端以 📌 展示)
|
||
|
||
### `search_text`(检索列)
|
||
|
||
内容 = `单词 + 各义项标题 + 词根 part/规范化键/含义`,统一小写。
|
||
**刻意不含例句正文**,避免例句里的无关词(如 "company" 含 "any")干扰检索。由 `buildWordSearchText()` 生成,在写入与启动迁移时刷新。
|
||
|
||
---
|
||
|
||
## 3. roots — 词根库(按词根维度,跨单词累积)
|
||
|
||
| 列 | 类型 | 约束 | 说明 |
|
||
|---|---|---|---|
|
||
| `id` | INTEGER | PK, AUTOINCREMENT | |
|
||
| `root` | TEXT | NOT NULL, **UNIQUE**(自动索引) | 规范化键:去连字符/非字母、小写,如 `lysis` |
|
||
| `display` | TEXT | NOT NULL | 展示形(保留连字符),如 `-tion`,以最近出现为准 |
|
||
| `type` | TEXT | | 前缀 / 词根 / 后缀 / 音节 |
|
||
| `phonetic` | TEXT | | 词根发音(IPA) |
|
||
| `words` | TEXT | NOT NULL, 默认 `'[]'` | 包含该词根的已学词,见下方 |
|
||
| `created_at` / `updated_at` | TEXT | NOT NULL | |
|
||
|
||
### `words` JSON 结构
|
||
|
||
```json
|
||
[
|
||
{
|
||
"word": "analysis",
|
||
"phonetic": "/əˈnæləsɪs/",
|
||
"meaning": "松开、解开",
|
||
"word_senses": ["n. 分析;解析", "n. 分解;剖析"]
|
||
}
|
||
]
|
||
```
|
||
|
||
- `meaning`:该词根**在此词中**体现的含义——刻意不做全局统一,多个词的含义变体并列展示,供学习者自行抽象
|
||
- `word_senses`:该单词自身的释义列表(词根面板点击单词揭晓时一并展示)
|
||
- 同一单词重复查询时条目整体覆盖;单词重新拆解后,从不再包含它的旧词根下自动摘除(词根下无词时整行删除)
|
||
|
||
---
|
||
|
||
## 4. 合并/维护逻辑(写入路径)
|
||
|
||
查询完成(流式返回 done 前)按顺序执行:
|
||
|
||
1. `upsertWordData(wordResult, sentence, sentenceTranslation)`
|
||
- 释义合并:`context_sense_id` 命中 → 并入原句 + 同义例句;否则新增义项
|
||
- `other_senses`:文案相同 → 例句并入已有义项;否则新增
|
||
- 词根同步:为 `roots` 中每个部分调用 `upsertRootData`,并按 `root_keys` 清理旧映射
|
||
- 刷新 `search_text`
|
||
2. `saveRecord(...)` 写入 `history`
|
||
|
||
## 5. 启动时自动迁移
|
||
|
||
- `words.root_keys`、`words.search_text`:缺失时 `ALTER TABLE` 补列
|
||
- `search_text` 每次启动对全表回填
|
||
- 历史版本说明:v1 仅 `history` 表;"按单词维度"版本引入 `words`(破坏性变更,经确认清除旧数据);当前版本追加 `roots`
|
||
|
||
## 6. 相关 API
|
||
|
||
| 方法 | 路径 | 说明 |
|
||
|---|---|---|
|
||
| GET | `/api/history?page=&size=&q=` | 历史分页列表,`q` 搜原句/单词 |
|
||
| GET | `/api/history/:id` | 历史详情 |
|
||
| PUT | `/api/history/:id` | 编辑保存 |
|
||
| DELETE | `/api/history/:id` | 删除 |
|
||
| GET | `/api/words?page=&size=&q=` | 词库分页列表,`q` 搜单词/释义/词根(不含例句) |
|
||
| GET | `/api/words/:word` | 单词档案 |
|
||
| GET | `/api/roots/:root` | 词根档案(键为规范化形式) |
|
||
| POST | `/api/query/stream` | 流式查询(写入全部三表) |
|