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>
108 lines
4.7 KiB
Markdown
108 lines
4.7 KiB
Markdown
# 商品档案公益 API 系统 — 规划方案 (v1.0 定稿)
|
||
|
||
> 公益网站/服务:采集全网商品信息,提供商品参数查询 API。**只收集 + 只提供信息,不涉及任何购买行为。**
|
||
|
||
---
|
||
|
||
## 1. 已锁定的决策
|
||
|
||
| # | 决策 | 结论 |
|
||
|---|------|------|
|
||
| 1 | 品类 | 首批 **食品快消** |
|
||
| 2 | 价格 | 只收 **官方标准零售价 (MSRP)**,静态字段,带来源/时间/地区/币种 + 免责说明;**不收实时电商价、不提供购买入口** |
|
||
| 3 | 技术栈 | **Go**(对外API/核心服务) + **Python**(采集/ETL/爬虫),经 PostgreSQL + Redis/队列解耦 |
|
||
| 4 | 种子数据 | ✅ **先导入 Open Food Facts 食品 dump**,最快拥有真实数据 |
|
||
| 5 | 数据许可 | 因采用 OFF → 对外数据库用 **ODbL** 并署名来源;CC0 来源(USDA)可自由混入 |
|
||
|
||
### 1.1 我先用的默认值(如不同意请指出,否则按此执行)
|
||
- **Go Web 框架**:`chi` + 标准库 `net/http`(轻量、稳定、易维护)。
|
||
- **地域范围**:先用 OFF **全球食品库**起步,后续接 **GS1-China** 补强中国市场数据。
|
||
- **数据库迁移工具**:Go 侧用 `golang-migrate`(纯 SQL 迁移,两端共享同一套 schema)。
|
||
- **部署**:初期 Docker Compose 一键起全套(Postgres/Redis/Go API/Python worker)。
|
||
|
||
---
|
||
|
||
## 2. 目标架构(定稿)
|
||
|
||
```
|
||
数据源(OFF dump / OFF API / USDA / GS1)
|
||
│
|
||
▼ Python: 采集 adapters → ETL(清洗/归一/去重/质量评分)
|
||
│
|
||
┌────▼─────────┐ 图片 ┌──────────┐
|
||
│ PostgreSQL │◀───────▶│ S3/MinIO │
|
||
│ (商品档案主库)│ └──────────┘
|
||
└────▲─────────┘
|
||
│ 只读 (+Redis缓存/限流)
|
||
▼ Go: 公开 REST API + OpenAPI 文档
|
||
各种软件 / 开发者
|
||
```
|
||
|
||
- **解耦契约**:两端通过共享 PostgreSQL schema + 一份《数据契约文档》协作,互不直接调用。
|
||
- **Go 端只读主库**(或读副本);**Python 端负责写入**。
|
||
|
||
---
|
||
|
||
## 3. 仓库结构(计划,写代码时落地)
|
||
|
||
```
|
||
goods/
|
||
├── README.md
|
||
├── docker-compose.yml # postgres + redis + minio + api + worker
|
||
├── docs/
|
||
│ ├── data-contract.md # 两端共享的字段契约
|
||
│ └── openapi.yaml # API 契约
|
||
├── migrations/ # 共享 SQL 迁移 (golang-migrate)
|
||
├── api/ # Go: 对外只读 API
|
||
│ ├── cmd/server/main.go
|
||
│ ├── internal/{handler,store,model,middleware}/
|
||
│ └── go.mod
|
||
└── ingestion/ # Python: 采集 + ETL
|
||
├── pyproject.toml
|
||
├── adapters/{openfoodfacts,usda,gs1}.py
|
||
├── etl/{normalize,dedup,quality}.py
|
||
└── jobs/{seed_off_dump,scheduler}.py
|
||
```
|
||
|
||
## 4. 数据模型 & API 契约
|
||
(沿用 v0.2:`product` 主表 + `food` 食品字段 + `msrp` 价格 + 辅助实体;API 以 `GET /products/barcode/{gtin}` 为核心,全只读、无交易端点。详见 v0.2 附件。)
|
||
|
||
---
|
||
|
||
## 5. 可执行任务拆分(按里程碑,写代码时逐项落地)
|
||
|
||
**M0 — 工程地基**
|
||
- [ ] 初始化 Go module (`api/`) + Python 项目 (`ingestion/`)
|
||
- [ ] `docker-compose.yml`:Postgres + Redis + MinIO
|
||
- [ ] CI(Go: build/vet/test;Python: ruff/pytest)
|
||
- [ ] `docs/data-contract.md` 初版
|
||
|
||
**M1 — 数据模型**
|
||
- [ ] `migrations/`:product / food / msrp / brand / manufacturer / category / source / attribute_definition / merge_log
|
||
- [ ] JSONB + GIN 索引;gtin 唯一索引
|
||
|
||
**M2 — 种子数据 (Python)**
|
||
- [ ] 下载 OFF 食品 dump(CSV)
|
||
- [ ] `seed_off_dump`:字段映射 → 入库(含营养/成分/过敏原/图片URL)
|
||
- [ ] USDA(CC0) 营养补全(可选)
|
||
|
||
**M3 — MVP API (Go)**
|
||
- [ ] 路由 + handler:barcode / id / search / nutriments / msrp / brands / categories / sources
|
||
- [ ] 统一响应、分页、`fields=` 裁剪、错误处理
|
||
- [ ] Redis 缓存 + IP 限流;`/healthz` + OpenAPI 文档
|
||
|
||
**M4 — 采集管线 (Python)**
|
||
- [ ] adapter:OFF API(增量更新)+ GS1(条码补全)
|
||
- [ ] ETL:清洗/单位归一/去重合并/质量评分/溯源
|
||
- [ ] 调度(定时增量更新)
|
||
|
||
**M5 — 开放与规模化**
|
||
- [ ] 搜索引擎(PG 全文 → OpenSearch)、CDN 缓存
|
||
- [ ] 免费 API Key(防滥用+统计)、众包纠错后台
|
||
- [ ] 开发者文档站 + 开放数据许可声明 + 站点"不提供购买"声明
|
||
|
||
---
|
||
|
||
## 6. 下一步
|
||
规划已定稿。**你说先不写代码,所以我暂停在这里**。等你说"开始",我就从 **M0 工程地基** 动手,搭好骨架后开 PR 给你看。也可以先只做某个里程碑(比如先 M0+M1 把骨架和数据模型立起来)。
|