7.1 KiB
商品数据清洗(Goods Data Cleaning)
本目录存放商品数据清洗相关的全部脚本与规则文件。清洗目标:把右侧 SDS 原产品库
(origin_goods)按规则批量配置为左侧官网商品(goods),替代后台手动逐个点击。
转换规则调查(2026-08-27,基于生产环境只读数据)
数据来源:
https://official.inkreach.cc/api生产接口(JWT 只读拉取):/origin-goods?page=1..3&pageSize=200(共 552 条)、/goods?page=1..2&pageSize=200(共 240 条)、/tags、/categories、/countries。未做任何写操作。 原始 JSON 快照存于runs/survey-2026-08-27/(已加入 .gitignore,不入库)。
1. 右侧原产品(origin_goods)命名结构
右侧只有一个字符串 goodName,整体模式:
国家(物流备注)品名-SKU-工艺位置[-仓库名]
↑ ↑ ↑ ↑ ↑
| | | | └─ 可选第4段:美西洛杉矶一仓 / 美中亚特兰大仓 等
| | | └─ 单面印花 / 双面印花 / 直喷双面 / 直喷单面 / 不打印 ...
| | └─ SKU 编码(字母+数字,如 DG001 / C1717 / KRHM003)
| └─ 包邮 / 不包邮 / DHL包邮*运费结算订单时支付 / 不包邮光板 等变体
└─ 美国/德国/韩国...(全角括号为主,少量半角混用)
统计(552 条):
- 541 条匹配
国家(备注)其余模式;11 条异常:- 4 条自定义商品(
Goods Origin ...,source=CUSTOM) - 2 条缺国家前缀:
(不包邮)230g水洗炒雪花T恤-双面印花/(不包邮)180g纯棉T恤成人款-... - 1 条用空格代替括号:
法国 180g纯棉T恤-FRTM001-双面印花 - 2 条半角左括号混用:
美国(不包邮)女士高弹中长款瑜伽运动裤-JSD004-... - 2 条同上变体
- 4 条自定义商品(
- 「备注)之后」按
-分段:387 条 = 3 段(品名-SKU-工艺)、154 条 = 4 段(品名-SKU-工艺-仓库) - 物流备注出现的变体形态(示例):
包邮、不包邮、DHL包邮、DHL包邮*运费结算订单时支付、包邮*运费订单结算时支付、不包邮光板 - 国家前缀出现过的值:美国、德国、英国、意大利、西班牙、西班牙直发、韩国、日本、加拿大、墨西哥、巴西、波兰、澳大利亚
2. 左侧已配置商品(goods)现状 —— 人工配置的实际结果
240 条 goods 记录,覆盖 209 个不同 origin_good_id(343 个 origin 尚未配置)。
没有系统级拆分逻辑:前端 GoodsView.vue 提交的是完整原名, 后端 goods.service.ts create/batchCreate 也原样入库。 因此左侧名称与右端的差异(113/240 条被改过)全部是人工在编辑弹窗里改的,且存在多种风格并存。
改名风格分布(113 条改名的归类):
| 风格 | 数量 | 示例 |
|---|---|---|
| A. 全拆:去前缀去括号,品名+空格+SKU,丢弃工艺段 | 27 | 韩国(包邮)200g纯棉T恤-KRTM001-单面印花 → 200g纯棉T恤 KRTM001 |
| B. 半改:仅把长备注缩成「X包邮」,其余原样保留 | 86 | 德国(DHL包邮*运费结算订单时支付)230g水洗T恤-DETM002-单面印花 → 德国(DHL包邮)230g水洗T恤-DETM002-单面印花 |
| R0. 保持原名不动 | 127 | 多为后期配置(2026-06 后期 ~ 07),未加工 |
标签体系(生产库现有 3 组 7 个标签)与左侧使用情况:
| 分组 | 标签(id) | 左侧使用次数 |
|---|---|---|
| 物流渠道 | 包邮(30) / 不包邮(31) | 87 / 153 ← 基本每个商品都挂了物流标签 |
| 印刷位置 | 双面印(35) / 单面印(34) | 14 / 14 ← 只有少数挂了 |
| 印刷工艺 | 烫画(32) / 直喷(33) / 不打印(42) | 11 / 3 / 1 |
其他字段:goodPriority 几乎全部为 5;positionId 全部为空;
国家字段与名称里的国家前缀一致率 238/240(仅 西班牙直发(...) 两条归入了「西班牙」)。
3. 从字符串解析出的隐含规则(草稿,待确认)
一条原产品字符串可以机械解析出以下信息(541/552 可完全机器解析):
| 解析项 | 来源 | 对应目标字段 |
|---|---|---|
| 国家 | 第一个 ( 之前文本(需处理:空格分隔、半角括号、「西班牙直发→西班牙」映射) |
countryId |
| 物流渠道 | 括号内含「包邮」与否 → 包邮 / 不包邮 | tag: 物流渠道 |
| 工艺/印刷位置 | 最后一段的 关键词:单面印花→单面印、双面印花→双面印、直喷→直喷、烫画→烫画、光板/不打印→不打印 | tags: 印刷位置 + 印刷工艺 |
| 展示名 | 目标形态(用户口径):品名 SKU(最后一个 - 连接改为空格连接,丢弃工艺/仓库段) |
goodName |
4. 待确认问题(规则定稿前必须回答)
- 展示名采用哪种?A 全拆(
200g纯棉T恤 KRTM001,推荐—— majority 且官网展示干净)还是 B 保留国家括号? - 同一基础商品的「单面印花」「双面印花」是拆成两个 goods(现状),还是合并为一个 good 并用标签区分? (注意 A 全拆后两者 goodName 完全相同,如 ITTM001 已出现重名两条)
- 历史 R0 的 127 条保持原名的记录是否要统一重命名?
- 未配置的 343 个 origin 是本次要全部自动配置的目标吗?(其中可能有不应上架的商品)
- 仓库名后缀(第 4 段)只做清洗忽略即可,还是需要保留到某个字段?
- 国家中文名 → countries 表的映射以
countryName精确匹配为准?缺失国家(如法国 FRTM001 对应的国家若不存在)如何处理?
执行流水线
[生产库]
│ ① 备份(pg_dump 全量,安全网)
▼
② apps/api/scripts/export-data.mjs 导出 JSON(现有脚本)
▼
③ sync-transform.mjs 转换脚本 + sync-rules.config.mjs 规则文件(本目录,待创建)
读取导出 JSON → 按规则加工 → 输出待导入 JSON + 变更摘要报告(人工检查点)
▼
④ apps/api/scripts/import-data.mjs 导入生产库(现有脚本)
▼
⑤ 验证:行数对比 / 抽查商品配置 / 官网公开 API 抽查
原则:三步式独立执行,每步可检查、可回滚;规则只改 sync-rules.config.mjs,不改代码;
导入前必须有全量备份;转换脚本为纯函数式(JSON in → JSON out),不直接连接数据库。
目录内容规划
| 文件 | 状态 | 说明 |
|---|---|---|
sync-rules.config.mjs |
待创建 | 同步规则文件(品类映射 / 国家分配 / 标签分配 / 优先级策略),规则未定,先占位 |
sync-transform.mjs |
待创建 | 数据转换脚本 |
runs/ |
待创建 | 每次执行的导出、转换产物与变更摘要报告(按日期归档);已含 survey-2026-08-27/ 调查快照(gitignore) |