Files
cat-shark 37b75c2d21 Initial commit: 查词学英语 MVP
- 流式查询(SSE 实时展示生成过程)
- 三维度数据模型:history(查询)/ words(单词档案)/ roots(词根档案)
- 词根拆解与发音拼读训练(词根点击揭晓历史词例)
- 词义/同义例句跨查询累积,同义项自动合并
- 历史与词库分页、多维度搜索
- 模型:Qwen3.6-35B-A3B(硅基流动,可 LLM_MODEL 切换)
2026-08-29 08:44:43 +08:00

174 lines
6.5 KiB
Markdown
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.
# 数据库表结构文档
> 数据库: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` | 流式查询(写入全部三表) |