forked from wangziqi/gongxue-base
feat: add pocketbase sqlite exporter
This commit is contained in:
@@ -74,7 +74,11 @@
|
||||
|
||||
3. 真实导入 dry-run
|
||||
- 从 PocketBase 导出现有用户、题库、单词、知识手册、分数线、订单、权益数据。
|
||||
- 已补 `npm run pb:import:dry-run` 静态迁移报告工具、`--profile=production` 生产迁移门禁、关键集合/关键字段覆盖率检查、strict warning 门禁测试和真实数据迁移验收 runbook;拿到真实导出后先跑 `npm run pb:import:dry-run -- --profile=production --json --fail-on-warnings`,再跑 `pb:import:json`、`pb:import:validate` 和业务抽样。
|
||||
- 已补 `npm run pb:export:sqlite` 只读 SQLite 导出工具,默认从 `F:\project\参考\旧题库数据库文件\data.db` 导出到 `.gitignore` 覆盖的 `pb_export/`,并生成 `sqlite-export-manifest.json`、`storage-manifest.json` 和脱敏统计。
|
||||
- 已补 `npm run pb:import:dry-run` 静态迁移报告工具、`--profile=production` 生产迁移门禁、关键集合/关键字段覆盖率检查、strict warning 门禁测试和真实数据迁移验收 runbook;真实 SQLite 已导出 58 个业务 collection、248555 条记录,并跑过 production dry-run。
|
||||
- 当前真实 dry-run 剩余 blocker:30 个订单缺 `userId`,其中 7 个 paid;22 个知识手册章节缺 `subjectId`。正式导入前必须补自动修复/隔离 mapper 和人工复核报告。
|
||||
- 当前真实 dry-run 剩余 mapper gap:`user_answer_records` 85442 条、`mock_exam_configs` 48 条、`referral_qrcodes` 79 条、`commission_settings` 1 条。它们分别对应学习历史/错题归因、全真模拟蓝图、推广码/小程序码、分佣设置,后续要进入标准化导入。
|
||||
- 处理完 blocker 后再跑 `npm run pb:import:dry-run -- --profile=production --json --fail-on-warnings`,再跑 `pb:import:json`、`pb:import:validate` 和业务抽样。
|
||||
- 对题目 JSON、单词、知识手册、分数线、视频走后端 preview/import API 做二次验证。
|
||||
|
||||
4. 部署配置
|
||||
|
||||
@@ -56,7 +56,7 @@ F:\project\参考\旧题库数据库文件
|
||||
storage/
|
||||
```
|
||||
|
||||
`data.db` 和 `auxiliary.db` 必须按只读源处理,不能直接在旧库上执行修复 SQL。后续应由本地转换脚本把 PocketBase SQLite 集合导出为规范 JSON,再进入下面的 dry-run/import 管线;`storage/` 中的附件、题图、PDF、视频封面等资源要同步生成资源迁移清单,最终进入 `content_assets` 和对象存储,不允许把旧本地路径或长效 URL 直接写给前端。
|
||||
`data.db` 和 `auxiliary.db` 必须按只读源处理,不能直接在旧库上执行修复 SQL。当前已补 `npm run pb:export:sqlite`,会用只读 SQLite 连接把 PocketBase collection 导出为规范 JSON,再进入下面的 dry-run/import 管线;`storage/` 中的附件、题图、PDF、视频封面等资源会同步生成资源迁移清单,最终进入 `content_assets` 和对象存储,不允许把旧本地路径或长效 URL 直接写给前端。
|
||||
|
||||
把 PocketBase 导出的集合 JSON 放到仓库根目录:
|
||||
|
||||
@@ -93,20 +93,61 @@ $env:PB_EXPORT_DIR="F:\migration\pb_export_20260630"
|
||||
npm run pb:import:dry-run
|
||||
```
|
||||
|
||||
如果输入源仍是 SQLite,而不是 JSON 目录,下一阶段需要先补 `scripts/import-pocketbase` 的 SQLite 只读导出命令,建议输出到仓库外或 `.gitignore` 覆盖的 `pb_export/`:
|
||||
如果输入源仍是 SQLite,而不是 JSON 目录,先执行 `scripts/import-pocketbase` 的 SQLite 只读导出命令,建议输出到仓库外或 `.gitignore` 覆盖的 `pb_export/`:
|
||||
|
||||
```powershell
|
||||
$env:PB_SQLITE_DIR="F:\project\参考\旧题库数据库文件"
|
||||
$env:PB_EXPORT_DIR="F:\project\pb_export"
|
||||
# 规划命令:npm run pb:export:sqlite
|
||||
npm run pb:export:sqlite
|
||||
```
|
||||
|
||||
导出脚本要求:
|
||||
导出脚本行为:
|
||||
|
||||
- 使用只读 SQLite 连接,禁止修改 `data.db`、`auxiliary.db` 和 `storage/`。
|
||||
- 每个 PocketBase collection 输出一个 JSON 文件,并保留旧 `id`、`created`、`updated`、relation 字段和文件字段。
|
||||
- 对 `users`、订单、支付、openid/unionid、手机号等敏感字段默认脱敏写 dry-run 报告;正式导入只在后端 mapper 中进入受控身份/订单/审计表。
|
||||
- 资源文件字段只输出相对路径、hash、size、mime 和旧 collection/record/file 三元组,后续由对象存储迁移步骤转为 `content_assets`。
|
||||
- `password`、`tokenKey`、`secret`、`wechatSessionKey`、短信验证码等密钥类字段默认不会写入普通 JSON;`openid/unionid` 默认也会移除,只在 `sqlite-export-manifest.json` 里记录字段和数量。后续如果确实要迁移第三方登录身份,必须走单独的加密身份迁移链路,不混入普通 `pb_export`。
|
||||
- 手机号、邮箱、业务旧 ID、订单、题目、学习记录等迁移必需字段会保留,用于自营 ToC 租户的数据归属和售后追溯。
|
||||
- 资源清单输出到 `storage-manifest.json`,包含相对路径、hash、size、mime 和旧 collection/record/file 三元组,后续由对象存储迁移步骤转为 `content_assets`。
|
||||
- `auxiliary.db` 默认只写 `_logs` 的数量和 level 摘要,不导出完整日志正文,避免把 UA、请求参数或历史 token 放进迁移数据包。
|
||||
|
||||
可选环境变量:
|
||||
|
||||
```powershell
|
||||
$env:PB_SQLITE_DATA_DB="F:\project\参考\旧题库数据库文件\data.db"
|
||||
$env:PB_SQLITE_AUX_DB="F:\project\参考\旧题库数据库文件\auxiliary.db"
|
||||
$env:PB_SQLITE_STORAGE_DIR="F:\project\参考\旧题库数据库文件\storage"
|
||||
$env:PB_SQLITE_COLLECTIONS="users,regions,subjects,categories,questions"
|
||||
$env:PB_SQLITE_BATCH_SIZE="2000"
|
||||
```
|
||||
|
||||
正常迁移不要设置 `PB_SQLITE_INCLUDE_SENSITIVE_IDENTITIES=true`。这个开关只允许在加密迁移工作区临时使用,并且导出的身份文件不得提交 Git。
|
||||
|
||||
当前真实库只读导出基线:
|
||||
|
||||
```text
|
||||
data.db: 58 个业务 collection,248555 条记录
|
||||
questions: 74102
|
||||
users: 3670
|
||||
orders: 636
|
||||
user_answer_records: 85442
|
||||
vocabulary: 3500
|
||||
handbook_entries: 2676
|
||||
storage-manifest: 9 个原始资源文件
|
||||
auxiliary.db: _logs 121715 条,仅摘要
|
||||
```
|
||||
|
||||
最近一次 production dry-run 仍有 2 个 blocker,需要在正式导入前处理:
|
||||
|
||||
- `orders.userId` 覆盖率 95.3%,30 个订单缺用户,其中 7 个为已支付订单。处理策略应优先从支付通知、手机号、订单号或人工售后记录找回用户;找不回的已支付订单必须进入人工异常台账,不允许静默开权益。
|
||||
- `handbook_chapters.subjectId` 覆盖率 94.4%,22 个章节缺所属手册。处理策略应按章节标题和条目归属归并到正确 `handbook_subjects`,无法归并的放入迁移隔离手册并标记待人工复核。
|
||||
|
||||
production dry-run 还有这些 warning,属于后续 mapper 或运营处理项:
|
||||
|
||||
- `user_answer_records` 85442 条尚未规范化到新练习历史/答题记录模型。
|
||||
- `mock_exam_configs` 48 条尚未规范化到 `practice_blueprints`。
|
||||
- `referral_qrcodes` 79 条尚未规范化到新推广码/小程序码模型。
|
||||
- `commission_settings` 1 条需要迁移到新分佣设置。
|
||||
- `dashboard_cache`、空 `customer_messages/smscodes/tenant_config` 可不作为正式数据源,必要时只保留审计摘要。
|
||||
|
||||
## 阶段 1:静态 Dry-Run
|
||||
|
||||
@@ -150,6 +191,7 @@ dry-run 会检查:
|
||||
- 用户、题目、订单、SVIP、激活码、单词、手册、分数线、视频等业务数量。
|
||||
- `production` profile 会额外检查生产迁移必需集合:`users`、`questions`、`subjects`、`categories`、`orders`、`svip_plans`、`codes`、`vocabulary_units`、`vocabulary`、`handbook_subjects`、`handbook_chapters`、`handbook_entries`。
|
||||
- `migrationReadiness.criticalFieldCoverage` 会统计关键字段覆盖率,例如 `users.phone`、`questions.subjectId/categoryId/content`、`orders.userId/planId/status`、`codes.code`、单词和手册的归属字段;生产模式下低于阈值会变成 blocker。
|
||||
- 对 SQLite 导出,`questions.categoryId` 会把 `nodeId` 视为新架构有效归属,`vocabulary.unitId` 会兼容旧字段 `unit`。
|
||||
|
||||
准入标准:
|
||||
|
||||
|
||||
Reference in New Issue
Block a user