需求设计:
-
用户登录注册:
- 以用户名为区分用户的指标,只实现一个用户名和密码登录的接口,核心不在这
-
输入英文单词:
-
如果在词库中:
-
按名词、动词、形容词等词性分类展示中文翻译
-
展示标签(四六级、雅思等)
-
展示英文例句(插入一条例句,则将该例句中所有单词添加到单词列表,再将例句添加到例句表),并显示中文翻译(如果没有翻译,就向云服务API发起调用,然后保存,最后返回)
-
展示近义词列表(中文翻译有一个相同则视为近义词),查近义词列表时,要查两遍(一遍word_id,一遍synonym)
-
展示派生词(自定义一个近似单词判断函数,巧用力扣<编辑距离>函数,计算把A变成B需要的最少操作次数,先通过长度差过大的筛选掉不可能的近义词,首字母不同的也直接筛掉,建立一个单词长度的数据库表,只差长度差不超过2的,再在这些长度不超过2的单词里找近义词)
-
展示该单词对应的短语(需要手动插入)
-
-
如果不在词库中:
- 向deepseek、gemini发起单词查询请求,按固定json格式返回
-
-
用户查询单词,该单词不在词库,或者服务端手动插入新的英文单词后(同时加上所有词性下的所有释义):
-
询问Char-Gpt该单词的所有词性与对应的中文释义,以json格式返回
-
根据多个中文释义查找该单词的近义词(在所有中文翻译有一个相同则视为近义词,查到近义词后,将近义词关系插入到近义词数据表中)
-
询问Chat-Gpt一条以该单词为核心词汇的例句,添加到例句数据库表
-
-
为某个英文单词新增中文释义
-
插入一条英文例句:
- 将该例句拆分为多个单词
2025年12月3日,突发奇想打算用go做一个模仿扇贝英语单词笔记的app,下面开始数据库设计:
vocabulary表:
|--------|-----|--------|---------------|-----|-----|
| Column | ID | word | pronunciation | Tag | 例句 |
| Type | int | string | string | int | int |
| E.g1 | 0 | "run" | /r/ | 1 | 3 |
近义词表/派生联想词表(relevant_word):(该近义词关系是双向的)
|--------|---------|---------|-------------|
| Column | Word_ID | Synonym | derivative |
| Type | int | string | string |
| E.g1 | 1 | "happy" | "good" |
| E.g2 | 2 | "nice" | "excellent" |
查找例句表:
- 插入某一条例句后,将该例句split, 然后将split后的单词加到这个表
|--------|---------|------|---|
| Column | word_id | 例句ID | |
| Type | int | int | |
| E.g | 0 | 3 | |
例句表:
- 新增一条例句后插入该表
|--------|------|------------------|---|-----------|
| Column | 例句ID | sentence | | translate |
| Type | int | TEXT | | TEXT |
| E.g | 3 | "I like running" | | "我喜欢跑步" |
中文单词表(core):
-
通过英文单词搜索中文释义时查找
-
添加英文单词的中文释义时插入
-
查找英文单词的中文释义以添加近义词关系时查找(如果)
|--------|---------|-----------|--------|
| Column | word_id | translate | pos |
| Type | int | string | string |
| | 1 | "橙子" | "n" |
| | 1 | "橘色的" | "adj" |
英文动词表 / 名词表 / 形容词表:(查找中文单词时搜索)
|--------|--------------|-----------|---|
| Column | word_id(可重复) | translate | |
| Type | int | string | |
| | 1 | "apple" | |
用户表(注册时添加)
|--------|---------|-----------|-----------|--------------|
| Column | User_id | User_name | pass_word | word_note_id |
| Type | | | | |
| | | | | |
生词本列表:(用户创建某个生词本时添加)
|--------|-----------|---------|---------|---|
| Column | Book_name | Book_id | User_id | |
| Type | | | | |
| | 生词本1 | 生词本1-id | 234421 | |
| | 四级词汇 | 四级词汇-id | 139879 | |
生词单:(用户将某个单词添加到自己的某个生词本里时添加关系)
|--------|---------|---------|
| Column | Book_id | word_id |
| | | |
Tag表示:从低到高依次为专升本、四级、六级、雅思、考研
1 1 1 1 1
核心架构调整理念
-
原子化设计 :单词 (
words)、释义 (definitions)、例句 (sentences)、标签 (tags) 必须完全解耦,通过中间表关联。 -
读写分离优化:
-
单词元数据 (拼写、音标)是静态的。
-
用户数据 (生词本、背诵进度)是高频变动的,必须拆分。
-
-
算法友好型字段 :为了你的"编辑距离"算法,我们需要在数据库层面预埋
word_length字段,避免全表扫描。
数据库表设计 (Schema Design)
建议使用 snake_case 命名数据库字段,符合 Go 的 GORM 或 SQLx 习惯。
1. 基础词汇表 (dict_words)
存储单词的物理属性。 加入了 word_length 和 first_char 方便你的派生词筛选算法。
2. 释义表 (dict_definitions)
一个单词可能有多个词性,每个词性可能有多个意思。 这里涵盖了你的"中文单词表"和"词性分类"需求。
3. 标签/考试库表 (dict_tags) & 关联表
解决一个单词既是"四级"也是"考研"词汇的问题。
dict_tags (标签定义) | Column | Type | Data | | :--- | :--- | :--- | | id | INT | 1 | | name | VARCHAR | "CET-4" |
rel_word_tags (单词-标签关联) | Column | Type | | :--- | :--- | | word_id | BIGINT | | tag_id | INT |
4. 例句库 (dict_sentences) & 单词关联
这里实现你的"插入一条例句,拆分所有单词并关联"的逻辑。
dict_sentences (例句本体) | Column | Type | Comment | | :--- | :--- | :--- | | id | BIGINT (PK) | 例句ID | | en_sentence | TEXT | 英文原句 (Hash Index) | | cn_sentence | TEXT | 中文翻译 | | source_type | VARCHAR | 来源 (AI, User, Dictionary) |
rel_word_sentences (倒排索引表) 这是核心!当你插入 "I like running" 时,Go 代码 split 后,会在这里插入三条记录,分别关联 I, like, running 的 word_id 和这个 sentence_id。 | Column | Type | Comment | | :--- | :--- | :--- | | word_id | BIGINT | 单词ID | | sentence_id | BIGINT | 例句ID |
5. 词汇关系表 (dict_relations)
整合你的"近义词"和"派生词"。 对于近义词 :利用中文释义匹配后存入。 对于派生词:利用编辑距离计算后存入(做缓存,不用每次都算)。
用户与学习系统 (User Space)
这里需要引入艾宾浩斯遗忘曲线的设计,这才是背单词 App 的灵魂。
6. 用户表 (users)
7. 生词本 (user_vocab_books)
8. 用户单词进度表 (user_word_progress)
这是最重要的一张表,记录用户对某个单词的熟悉程度。
核心业务逻辑实现思路 (Go Implementation Tips)
1. 派生词查找算法 (优化版)
你的需求是:计算 A 变成 B 的最少操作次数 (Levenshtein Distance),且首字母相同,长度差 <= 2。
SQL 预筛选 (Go代码中执行): 假设用户查单词 "apple" (长度5,首字母a)。 不要直接把数据库所有词拿出来算编辑距离,那样会卡死。
Go 内存计算: 拿到上述 SQL 返回的几百个候选词,在 Go 协程中并发计算编辑距离,筛选出距离 < 3 的词,返回给前端。
2. AI 兜底策略 (Lazy Loading)
当用户查询 dict_words 表发现不存在时:
-
Sync (同步): Go 后端立即调用 Deepseek/Gemini API。
-
Wait (等待): 解析 JSON。
-
Write (写入):
-
写入
dict_words。 -
写入
dict_definitions。 -
Async (异步): 启动一个 goroutine 去做"重活":
-
问 AI 要例句 -> 插入
dict_sentences-> Split 句子 -> 插入rel_word_sentences。 -
根据中文释义反查库里的词 -> 插入
dict_relations(近义词)。
-
-
-
Return: 返回单词详情给用户。
3. 例句的反向索引 (Reverse Indexing)
当管理员或 AI 插入例句 "He runs fast" 时:
-
Go
strings.Split-> ["he", "runs", "fast"]。 -
进行词形还原 (Lemmatization) (推荐使用库,如 go-en):
- "runs" -> "run"。
-
遍历单词:
-
查找 "run" 的
id。 -
插入
rel_word_sentences(word_id=run_id, sentence_id=new_id)。 这样,当你查 "run" 这个词时,虽然例句里写的是 "runs",用户依然能看到这个例句。
-
拓展功能建议 (Feature Extension)
-
每日热力图 (GitHub Style)
- 记录用户每天背了多少个单词,在前端展示类似 GitHub 的绿色方块图,增加用户粘性。
-
单词打卡与分享
- 生成一张带有背景图、单词、例句和二维码的图片(Go 有很多绘图库如
gg),方便用户发朋友圈。
- 生成一张带有背景图、单词、例句和二维码的图片(Go 有很多绘图库如
-
短语/固定搭配表 (
dict_phrases)- 除了单词,像 "look forward to" 这种短语也需要作为单独的实体存库,或者作为
word表的一种特殊类型。
- 除了单词,像 "look forward to" 这种短语也需要作为单独的实体存库,或者作为
-
发音 TTS 缓存
- 接入 OpenAI TTS 或 Edge-TTS,生成单词的 MP3,存到对象存储 (MinIO/S3),数据库只存 URL。