danci 3:几千个单词怎么导进数据库?从 JSON 数据清洗到 AI Coding

28 阅读11分钟

words 表已经设计好了。

但是数据库里还是空的。

如果一个词一个词手工录入,几千个单词可能要录到怀疑人生。

真实项目里,这种数据到底应该怎么处理?

这个问题会把数据清洗、脚本、AI 上下文、AGENTS.md、Prompt 颗粒度和 Git 全部串起来。


一、先解决最现实的问题:单词从哪里来?

danci 需要大量单词数据。

例如:

四级
六级
考研
雅思
托福

如果全部人工录入:

apple
ability
abandon
...

成本太高。

一种更现实的做法是:

找到质量较高、许可允许使用的开源词库作为原始数据源。

例如从 GitHub 下载词库:

GitHub
↓
ZIP
↓
JSON

假设得到一个:

words.json

问题看起来似乎已经解决了。

但实际上,下一个问题马上出现。


二、有 JSON 了,为什么不能直接导进数据库?

因为外部数据是按照:

别人项目的数据结构

设计的。

而 danci 的 words 表是按照:

自己的业务

设计的。

例如原始 JSON:

{
  "word": "apple",
  "trans": ["苹果", "苹果公司"],
  "phonetic": "ˈæpəl",
  "tag": "cet4",
  "other": "..."
}

而数据库真正想要的可能是:

word
meaning
phonetic

甚至还可能出现:

同一个单词重复
meaning 为空
字段格式不一致
多余字段
脏字符
错误释义

所以:

下载 JSON
↓
直接导数据库

中间其实少了一层。

这就是:

数据清洗。


三、数据清洗不是简单的“JSON 转 CSV”

如果只是:

.json
↓
.csv

这叫格式转换。

真实的数据清洗通常还要做:

字段选择
字段重命名
格式统一
去重
过滤异常数据
处理缺失值
校验
审核

例如:

原始 JSON
↓
只保留需要字段
↓
统一 meaning 格式
↓
删除重复单词
↓
过滤缺失 word 的记录
↓
抽样检查
↓
生成 CSV
↓
导入数据库

所以数据清洗的核心不是:

换一个文件后缀。

而是:

把外部数据整理成符合当前系统业务约束的数据。


四、为什么这是一个很典型的后端任务?

真实后端开发经常需要面对:

CSV
Excel
JSON
第三方 API
旧数据库
日志
爬虫数据
批量导入
数据迁移

这些数据很少能直接进入业务数据库。

所以实际工程中经常会出现:

scripts/

例如:

scripts/
├── convert-words.ts
├── validate-words.ts
└── import-words.ts

这些脚本不是用户在线操作的业务接口。

它们主要负责:

数据转换
数据清洗
数据导入
初始化
批处理
爬虫
一次性修复

所以:

scripts 不是“随手写几个临时代码”的地方,它本身就是非常常见的工程工具。


五、既然有 AI,直接把整个 JSON 发给 AI 不行吗?

当然可以想到:

把 words.json 发给 AI
↓
让 AI 转成 CSV

如果数据很小,偶尔这么做并没有什么问题。

但是当文件越来越大:

100 KB
1 MB
10 MB
...

问题就开始出现了。

模型需要读取大量原始数据:

上下文被占用
↓
token 消耗增加
↓
真正重要的业务规则反而被淹没

而且如果清洗规则改了:

重新发文件
↓
重新处理

整个过程并不稳定。


六、其实 AI 根本不需要看到全部数据

假设原始数据有 10000 条。

AI 真正需要知道的往往只是:

输入长什么样

{
  "word": "apple",
  "trans": ["苹果"]
}

输出想要什么

word,meaning
apple,苹果

转换规则是什么

trans 只取第一个释义
word 为空时过滤
同名 word 去重
输出 UTF-8 CSV

有这些信息以后,AI 已经可以写程序了。

所以更好的方式是:

告诉 AI 数据格式和规则
↓
让 AI 写脚本
↓
本地程序处理完整数据

七、让 AI 写程序,而不是让 AI 手工处理 10000 条数据

例如让 AI 生成:

scripts/convert-words.ts

脚本完成:

读取 words.json
↓
遍历全部记录
↓
字段转换
↓
去重
↓
过滤异常记录
↓
生成 words.csv

于是工作方式从:

LLM 直接处理 10000 条数据

变成:

LLM 写 100 行程序
↓
程序处理 10000 条数据

这两种方式的意义完全不同。

第二种方式:

可重复
可修改
可测试
可 Review
可以加入 Git

这其实是 AI Coding 很重要的一种思路:

对于规则明确、数据量大、重复度高的任务,AI 最有价值的角色往往不是亲自处理数据,而是帮我们生成处理数据的工具。


八、这件事本质上也是“上下文管理”

AI Coding 并不是:

给 AI 越多文件越好

真正需要的是:

足够
准确
相关

的上下文。

例如只是要生成 JSON → CSV 的脚本,模型可能只需要:

3 条原始数据样例
目标 CSV 格式
字段规则
异常处理规则

不一定需要完整读取:

整个 138 KB / 1 MB / 更大的 JSON

这就是所谓的:

不要让无关或可以由程序处理的信息占满模型上下文。


九、但另一个极端也不行:上下文太少

如果直接告诉 Coding Agent:

帮我做 books 管理

它不知道:

项目是 Next.js 还是 Vue?

UI 用什么?

数据库在哪里?

books 有哪些字段?

ORM 用什么?

删除时是否 cascade?

管理员有什么权限?

代码应该放哪个目录?

于是模型只能:

而 AI 写业务代码时,最危险的事情之一就是:

业务规则没写清楚,模型自己脑补了一套看起来合理的逻辑。

所以 AI Coding 的问题不是:

上下文越少越好

而是:

不要给无关上下文
+
必须给足关键上下文

十、Prompt 颗粒度到底是什么意思

比较:

Prompt A

实现单词书管理。

Prompt B

实现 /books 单词书管理。

技术约束:
- Next.js + TypeScript
- 使用项目现有 shadcn/ui
- 使用现有 Drizzle db 与 schema

功能:
- 查询单词书
- 创建单词书
- 修改单词书
- 删除单词书

字段:
- name:必填
- description:可选

业务规则:
- 删除前二次确认
- 不修改无关页面
- 复用已有组件

第二个 Prompt 并不是单纯:

字更多

而是它明确了:

做什么
使用什么
数据是什么
规则是什么
边界是什么

所以 Prompt 颗粒度真正想表达的是:

把任务拆到模型可以明确执行和验收的程度,不要把关键业务决定留给模型猜。


十一、可是这些技术栈难道每次都要重新写?

假设每次都写:

我们使用 Next.js
我们使用 Drizzle
我们使用 shadcn/ui
我们使用 Tailwind CSS
数据库是 Supabase PostgreSQL
提交使用 Conventional Commits
...

会产生大量重复。

这些信息属于:

长期项目上下文

所以可以放在:

AGENTS.md

一类项目级规则文件中。

例如:

# Tech Stack

- Next.js
- TypeScript
- shadcn/ui
- Tailwind CSS
- Supabase PostgreSQL
- Drizzle ORM

# Rules

- 优先复用 components/ui
- 不修改无关文件
- 数据库结构以 db/schema.ts 为准
- 提交遵循 Conventional Commits

然后当前 Prompt 只写:

这一次具体做什么

于是形成:

AGENTS.md
↓
长期规则

Prompt
↓
当前任务

这就比每次把整个项目重新介绍一遍更稳定。


十二、让 AI 了解 Supabase 里的 books 表,最好的方式是什么?

如果只是告诉模型:

Supabase 里面有 books 表

信息还不够。

它仍然不知道:

字段
类型
主键
外键
约束

而项目本地已经有:

db/schema.ts

例如:

export const books = pgTable("books", {
  id: serial("id").primaryKey(),
  name: varchar("name", { length: 255 }).notNull(),
})

那么 Coding Agent 直接读取 schema 就可以知道:

books 表到底长什么样

这说明一个非常重要的工程思想:

最好的 AI 上下文不一定全部写在 Prompt 里。清晰的代码、schema、类型、测试和项目文档本身就是上下文。


十三、为什么“阻止 AI 读文件”也不能理解得太绝对

大文件会消耗上下文,所以:

不要无脑把所有文件全读一遍

是对的。

但这并不等于:

AI 不应该读项目文件

恰恰相反。

开发任务需要模型读取:

相关代码
schema
类型
已有组件
项目规则
测试

真正应该避免的是:

与任务无关的文件
大量原始数据
无意义的历史材料

所以准确原则应该是:

控制上下文范围,而不是禁止上下文。


十四、数据清洗脚本跑完以后,能直接相信吗?

不能。

假设 AI 生成:

convert-words.ts

运行后输出:

words.csv

还应该继续做:

检查总行数
检查空字段
检查重复词
随机抽样
核对几个典型单词

也就是说:

AI 生成脚本
≠
结果自动正确

正确流程应该是:

AI 生成
↓
本地执行
↓
验证结果
↓
发现问题
↓
修改规则
↓
重新执行

这就是:

AI 负责提高实现速度,人仍然负责定义规则和验收结果。


十五、AI 一次改了十几个文件怎么办?

Coding Agent 的另一个特点是:

改代码很快

一个任务可能同时修改:

页面
组件
schema
接口
配置
测试

如果没有版本控制,很难回答:

它到底改了什么?

哪些改动是预期的?

哪里改错了?

怎么恢复?

所以 AI Coding 时代,Git 反而更加重要。

开发完成后至少应该:

查看 git diff
↓
Review 修改
↓
运行测试
↓
确认功能
↓
提交

十六、Conventional Commits 在这里解决什么?

Git commit 如果全部写:

update
修改
改一下
完成

时间久了很难知道每次提交做了什么。

Conventional Commits 给提交信息一个统一格式。

常见类型:

feat
新增功能

fix
修复 Bug

docs
文档修改

refactor
重构

style
样式或格式修改

test
测试

chore
工程配置 / 工具类修改

例如:

feat: add books management

表示:

新增单词书管理功能
fix: handle duplicate words during import

表示:

修复导入时重复单词的问题

它真正解决的是:

让 Git 历史变得清晰、统一、可追踪。


十七、把整个数据导入过程重新走一遍

现在终于可以把完整流程串起来:

GitHub 获取开源单词数据
↓
下载 JSON
↓
分析原始结构
↓
确定 words 表需要哪些字段
↓
定义清洗规则
↓
让 AI 编写 scripts/convert-words.ts
↓
本地执行
↓
生成 CSV
↓
校验 / 抽样审核
↓
导入 Supabase PostgreSQL

这就是一个完整的数据清洗流程。

而不是:

下载 JSON
↓
扔给 AI
↓
得到 CSV
↓
结束

十八、再把 AI Coding 流程走一遍

项目长期信息:

AGENTS.md
schema.ts
已有代码
已有组件

负责告诉 AI:

这个项目是什么

当前 Prompt:

任务
业务规则
范围
验收标准

负责告诉 AI:

这次要做什么

AI 完成后:

git diff
↓
Review
↓
测试
↓
Conventional Commit

负责回答:

AI 做得对不对

于是整个工作流变成:

项目上下文
↓
明确任务
↓
Coding Agent 实现
↓
人工验收
↓
Git 管理

十九、这三个部分其实是一回事

这一篇涉及多个内容:

数据清洗
scripts
AI 上下文
Prompt
AGENTS.md
Git

但它们背后的思想其实非常统一:

面对大量重复数据

不要让人手工处理
↓
写程序批量处理

面对 AI

不要让 AI 猜
↓
提供准确上下文和规则

面对大量代码修改

不要直接相信结果
↓
Review + Test + Git

最终都是在做一件事:

把人的精力从重复执行中释放出来,放到规则设计、架构判断和结果验收上。


二十、整个 danci 系列最终串起来

第一篇解决:

为什么需要后台?

得到:

后台 + H5
Next.js
shadcn/ui
管理员体系

第二篇解决:

后台的数据存在哪里?

得到:

Supabase PostgreSQL
Drizzle ORM
schema
migration
relation
RLS

第三篇解决:

真实数据怎么进入系统?
AI 怎么参与项目开发?

得到:

数据清洗
scripts
上下文管理
AGENTS.md
Prompt
Git

最终,danci 不再只是:

一个背单词 Demo

它开始包含一个真实项目会遇到的完整问题链:

业务设计
↓
后台管理
↓
数据库建模
↓
权限控制
↓
真实数据处理
↓
AI 辅助开发
↓
工程化验收

真正值得学习的,也正是这条从“功能能跑”走向“项目可维护”的过程。