54175238ad
新增 docs/planning/ 规划文档归档: - 00-final-plan: 最终规划(决策+架构+M0~M5任务清单) - 01-detailed-design-v2.0: 分类/单位/数据库/API/治理/采集/部署/众包 - 02-advanced-topics-v3.0: OpenAPI/全表DDL/数据契约/OFF映射/中国合规/测试/安全/图片/SLA/竞品 - history/: v0.1~v1.0 演进记录 更新 README 为项目介绍并链接规划文档。 Co-Authored-By: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
116 lines
5.4 KiB
Markdown
116 lines
5.4 KiB
Markdown
# 天工·商品标签 (OpenGoods) — 最终规划 (Final)
|
||
|
||
> 公益网站/服务:采集全网商品信息,提供商品参数查询 API。
|
||
> **核心原则:只采集 + 只提供信息,绝不涉及任何购买/下单/比价导购。**
|
||
> 本文档为前几版(v0.1 → v2.0)的最终收敛版,所有关键决策已锁定。详细设计见 v2.0 附件。
|
||
|
||
---
|
||
|
||
## 0. 项目标识
|
||
- **中文名**:天工·商品标签(呼应《天工开物》)
|
||
- **英文名**:OpenGoods
|
||
- **定位**:开放、中立、可溯源的"商品参数百科 + 开放 API"
|
||
|
||
---
|
||
|
||
## 1. 已锁定的全部决策
|
||
|
||
| 维度 | 决策 |
|
||
|------|------|
|
||
| 首批品类 | **食品快消** |
|
||
| 价格 | 只收 **官方标准零售价 (MSRP)**:静态字段,带 currency/region/source/effective_date + 免责;**不收实时电商价、无购买入口** |
|
||
| 技术栈 | **Go**(对外只读 API/核心服务) + **Python**(采集/ETL/爬虫),经 **PostgreSQL + Redis/队列** 解耦 |
|
||
| 种子数据 | **Open Food Facts 食品 dump** 先导入,最快有真实数据 |
|
||
| 数据许可 | 对外数据库用 **ODbL + 署名**;CC0 来源(USDA)自由混入;每条数据按来源标注许可 |
|
||
| 商品分类 | **GS1 GPC 四层标准码 (Segment→Family→Class→Brick)** 为骨架 + **自建中文品类树** 映射 + 保留来源原始分类 |
|
||
| 单位管理 | 量纲字典;**原始值 + 归一化值双存**;营养统一折算到 `per_100g/per_100ml`;能量 **双存 kJ+kcal**;用十进制(NUMERIC)防误差 |
|
||
| 质量评分 | `0.4*完整度 + 0.3*来源权威 + 0.2*多源一致 + 0.1*新鲜度` |
|
||
| 众包 | **一期不做众包,先纯采集**;二期再开放贡献/纠错(带审核与版本化) |
|
||
| Go 框架 | `chi` + 标准库 `net/http`(轻量) |
|
||
| 迁移工具 | `golang-migrate`(纯 SQL,两端共享 schema) |
|
||
| 部署 | 初期 Docker Compose(postgres+redis+minio+go-api+python-worker)→ 后期 K8s |
|
||
| 地域 | 先用 OFF 全球食品库起步,后接 GS1-China 补强中国数据 |
|
||
|
||
---
|
||
|
||
## 2. 架构(定稿)
|
||
|
||
```
|
||
数据源: OFF dump / OFF API / USDA(CC0) / GS1-China
|
||
│
|
||
▼ Python: 采集 adapters → ETL(清洗/单位归一/分类映射/去重/质量评分)
|
||
│ 写入
|
||
┌────▼─────────┐ 图片 ┌──────────┐
|
||
│ PostgreSQL │◀───────▶│ MinIO/S3 │
|
||
│ (商品档案主库)│ └──────────┘
|
||
└────▲─────────┘
|
||
│ 只读 (+Redis 缓存/限流)
|
||
▼ Go: 公开 REST API + OpenAPI 文档
|
||
各种软件 / 开发者 (无任何交易端点)
|
||
```
|
||
两端不直接互调,通过共享 PostgreSQL schema + 《数据契约文档》协作。
|
||
|
||
---
|
||
|
||
## 3. 仓库结构(写代码时落地)
|
||
```
|
||
goods/ (OpenGoods 天工·商品标签)
|
||
├── README.md
|
||
├── LICENSE # 代码: Apache-2.0/MIT; 数据: ODbL 说明
|
||
├── docker-compose.yml
|
||
├── docs/{data-contract.md, openapi.yaml, disclaimer.md}
|
||
├── migrations/ # golang-migrate 共享 SQL
|
||
├── api/ # Go 只读 API (chi)
|
||
│ ├── cmd/server/main.go
|
||
│ └── internal/{handler,store,model,middleware}/
|
||
└── ingestion/ # Python 采集 + ETL
|
||
├── adapters/{openfoodfacts,usda,gs1}.py
|
||
├── etl/{normalize_units,map_category,dedup,quality}.py
|
||
└── jobs/{seed_off_dump,scheduler}.py
|
||
```
|
||
|
||
---
|
||
|
||
## 4. 最终可执行任务清单(按里程碑)
|
||
|
||
**M0 — 工程地基**(~3–5d)
|
||
- [ ] Go module + Python 项目骨架
|
||
- [ ] docker-compose(postgres+redis+minio)
|
||
- [ ] CI(Go build/vet/test;Python ruff/pytest)
|
||
- [ ] `docs/data-contract.md`、`docs/disclaimer.md`(不提供购买声明)初版
|
||
|
||
**M1 — 数据模型 + 分类 + 单位**(~4–6d)
|
||
- [ ] migrations:product / food_detail / product_msrp / product_source / brand / manufacturer / category / category_schema / unit / attribute_definition / merge_log
|
||
- [ ] 导入 GS1 GPC 骨架 + 建自建中文品类树 + 映射表
|
||
- [ ] 单位字典 + 归一化规则
|
||
- [ ] 索引:gtin 唯一、name trigram、JSONB GIN、category ltree
|
||
|
||
**M2 — 种子数据 (Python)**(~5–8d)
|
||
- [ ] 下载 OFF 食品 dump → 字段映射(成分/营养/过敏原/图片)
|
||
- [ ] 单位归一 + 分类映射入库
|
||
- [ ] USDA(CC0) 营养补全(可选)
|
||
|
||
**M3 — MVP API (Go)**(~5–8d)
|
||
- [ ] 端点:barcode / id / search / nutriments / msrp / brands / categories / sources / healthz
|
||
- [ ] 统一响应信封、分页、`fields=` 裁剪、错误码
|
||
- [ ] Redis 缓存 + IP 限流 + OpenAPI 文档
|
||
|
||
**M4 — 采集管线 (Python)**(~8–12d)
|
||
- [ ] adapter:OFF API 增量 + GS1 条码补全
|
||
- [ ] ETL:清洗/归一/去重合并/冲突解决/质量评分/字段级溯源
|
||
- [ ] 调度(定时增量更新)
|
||
|
||
**M5 — 开放与规模化**(~10–15d)
|
||
- [ ] 搜索引擎(PG 全文 → OpenSearch)、CDN
|
||
- [ ] 免费 API Key(防滥用+统计)
|
||
- [ ] 众包贡献后台(提交/审核/版本/信誉)
|
||
- [ ] 开发者文档站 + 开放数据许可与免责声明上线
|
||
|
||
> 关键路径:M0→M1→M2→M3(最快拿到可查询 MVP);M4/M5 后续并行迭代。
|
||
|
||
---
|
||
|
||
## 5. 下一步
|
||
规划已全部定稿。你之前说"先不写代码",所以我**停在这里待命**。
|
||
等你说"开始",我从 **M0 工程地基** 动手,搭好骨架后开 PR 给你看(也可指定先只做某几个里程碑,例如 M0+M1)。
|