Files
goods/docs/planning/00-final-plan.md
lixu 54175238ad docs: 归档天工·商品标签(OpenGoods)规划文档
新增 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>
2026-06-08 06:05:29 +00:00

116 lines
5.4 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 天工·商品标签 (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 Composepostgres+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 — 工程地基**~35d
- [ ] Go module + Python 项目骨架
- [ ] docker-composepostgres+redis+minio
- [ ] CIGo build/vet/testPython ruff/pytest
- [ ] `docs/data-contract.md``docs/disclaimer.md`(不提供购买声明)初版
**M1 — 数据模型 + 分类 + 单位**~46d
- [ ] migrationsproduct / 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)**~58d
- [ ] 下载 OFF 食品 dump → 字段映射(成分/营养/过敏原/图片)
- [ ] 单位归一 + 分类映射入库
- [ ] USDA(CC0) 营养补全(可选)
**M3 — MVP API (Go)**~58d
- [ ] 端点:barcode / id / search / nutriments / msrp / brands / categories / sources / healthz
- [ ] 统一响应信封、分页、`fields=` 裁剪、错误码
- [ ] Redis 缓存 + IP 限流 + OpenAPI 文档
**M4 — 采集管线 (Python)**~812d
- [ ] adapterOFF API 增量 + GS1 条码补全
- [ ] ETL:清洗/归一/去重合并/冲突解决/质量评分/字段级溯源
- [ ] 调度(定时增量更新)
**M5 — 开放与规模化**~1015d
- [ ] 搜索引擎(PG 全文 → OpenSearch)、CDN
- [ ] 免费 API Key(防滥用+统计)
- [ ] 众包贡献后台(提交/审核/版本/信誉)
- [ ] 开发者文档站 + 开放数据许可与免责声明上线
> 关键路径:M0→M1→M2→M3(最快拿到可查询 MVP);M4/M5 后续并行迭代。
---
## 5. 下一步
规划已全部定稿。你之前说"先不写代码",所以我**停在这里待命**。
等你说"开始",我从 **M0 工程地基** 动手,搭好骨架后开 PR 给你看(也可指定先只做某几个里程碑,例如 M0+M1)。