update
This commit is contained in:
21
db/migrations/2026-09-21-01-street-main-detail.sql
Normal file
21
db/migrations/2026-09-21-01-street-main-detail.sql
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
-- 2026-09-21-01 街拍主副图:草稿表 / 正式表的图片表各加两列。
|
||||||
|
--
|
||||||
|
-- 对应规格:docs/superpowers/specs/2026-09-21-street-main-detail-design.md §3.1
|
||||||
|
-- is_detail 0=主图 1=副图
|
||||||
|
-- parent_image_id 副图指向所属主图的「行 id」;主图为 0
|
||||||
|
-- (存行 id 而非序号:序号会因重排 / 插入 / 删除而失效)
|
||||||
|
--
|
||||||
|
-- 幂等:全部 ADD COLUMN IF NOT EXISTS,可重复执行。
|
||||||
|
-- 存量行为 0/0,即「全部按主图渲染」,无需数据迁移。
|
||||||
|
--
|
||||||
|
-- 应用后请重新导出结构,否则目标库拿不到新列:
|
||||||
|
-- ./bin/dbtool dump -clean -out db/backups/db_dump.sql
|
||||||
|
--
|
||||||
|
-- 说明:规格未给 parent_image_id 建索引。图片表当前规模为千行级(street_snap_draft_images
|
||||||
|
-- 1052 行),按 (draft_id) 过滤走顺序扫描即可;若日后量级变大需要,再按读侧实际查询补索引。
|
||||||
|
|
||||||
|
ALTER TABLE street_snap_draft_images ADD COLUMN IF NOT EXISTS is_detail smallint NOT NULL DEFAULT 0;
|
||||||
|
ALTER TABLE street_snap_draft_images ADD COLUMN IF NOT EXISTS parent_image_id integer NOT NULL DEFAULT 0;
|
||||||
|
|
||||||
|
ALTER TABLE street_snap_images ADD COLUMN IF NOT EXISTS is_detail smallint NOT NULL DEFAULT 0;
|
||||||
|
ALTER TABLE street_snap_images ADD COLUMN IF NOT EXISTS parent_image_id integer NOT NULL DEFAULT 0;
|
||||||
49
db/migrations/2026-09-21-02-duplicate-review.sql
Normal file
49
db/migrations/2026-09-21-02-duplicate-review.sql
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
-- 2026-09-21-02 重复检测与审核展示:新建 image_duplicates 表 + 街拍正式表按文章做键。
|
||||||
|
--
|
||||||
|
-- 对应规格:docs/superpowers/specs/2026-09-21-duplicate-review-design.md §3.1 / §3.7
|
||||||
|
--
|
||||||
|
-- 幂等:CREATE TABLE / CREATE INDEX 全带 IF NOT EXISTS,ADD COLUMN 带 IF NOT EXISTS,
|
||||||
|
-- 可重复执行。
|
||||||
|
--
|
||||||
|
-- 应用后请重新导出结构:
|
||||||
|
-- ./bin/dbtool dump -clean -out db/backups/db_dump.sql
|
||||||
|
|
||||||
|
-- ---------------------------------------------------------------------------
|
||||||
|
-- ① 重复图对表(读时预计算并落库,替代不可反查的 is_duplicate / dup_of 两列)
|
||||||
|
-- ---------------------------------------------------------------------------
|
||||||
|
-- kind / owner_kind 等字符串列控制长度而不做 CHECK 约束:与项目既有表风格一致
|
||||||
|
-- (brand_runway_drafts.status 等也是裸 varchar),避免新增约束带来的迁移负担。
|
||||||
|
CREATE TABLE IF NOT EXISTS image_duplicates (
|
||||||
|
id BIGSERIAL PRIMARY KEY,
|
||||||
|
kind varchar(16) NOT NULL, -- runway | street
|
||||||
|
-- 本方(「这张图」)
|
||||||
|
image_id integer NOT NULL, -- 图片行 id
|
||||||
|
owner_kind varchar(8) NOT NULL, -- draft | official
|
||||||
|
owner_id integer NOT NULL, -- 草稿 id 或正式表主键
|
||||||
|
-- 对手(「和它重复的那张」)
|
||||||
|
peer_image_id integer NOT NULL,
|
||||||
|
peer_owner_kind varchar(8) NOT NULL,
|
||||||
|
peer_owner_id integer NOT NULL,
|
||||||
|
created_at integer NOT NULL DEFAULT 0
|
||||||
|
);
|
||||||
|
|
||||||
|
-- 唯一索引:保证重复配对计算幂等(写入侧用 ON CONFLICT ... DO NOTHING)
|
||||||
|
CREATE UNIQUE INDEX IF NOT EXISTS uq_image_dups_pair
|
||||||
|
ON image_duplicates (kind, owner_kind, image_id, peer_owner_kind, peer_image_id);
|
||||||
|
|
||||||
|
-- 辅助索引:读侧按草稿 / 专辑批量取数(审核详情页)
|
||||||
|
CREATE INDEX IF NOT EXISTS idx_image_dups_owner
|
||||||
|
ON image_duplicates (kind, owner_kind, owner_id);
|
||||||
|
|
||||||
|
-- ---------------------------------------------------------------------------
|
||||||
|
-- ② 街拍正式表:新增 source / source_url,供「一篇文章一张专辑」的实体键使用
|
||||||
|
-- ---------------------------------------------------------------------------
|
||||||
|
-- 用 not null default '' 而不是可空:NULL 在唯一索引里不参与比较,
|
||||||
|
-- 会造成「同键可重复插入」的漏洞。
|
||||||
|
ALTER TABLE street_snaps ADD COLUMN IF NOT EXISTS source varchar(32) NOT NULL DEFAULT '';
|
||||||
|
ALTER TABLE street_snaps ADD COLUMN IF NOT EXISTS source_url varchar(512) NOT NULL DEFAULT '';
|
||||||
|
|
||||||
|
-- 必须是**部分**索引:存量行 source_url 为空串,全量唯一索引会因大量 ('','') 冲突
|
||||||
|
-- 而建索引失败。
|
||||||
|
CREATE UNIQUE INDEX IF NOT EXISTS uq_ss_source
|
||||||
|
ON street_snaps (source, source_url) WHERE source_url <> '';
|
||||||
27
db/migrations/2026-09-21-03-ingest-source-idempotency.sql
Normal file
27
db/migrations/2026-09-21-03-ingest-source-idempotency.sql
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
-- 2026-09-21-03 来源幂等:两张草稿表新增 source / source_url,并建部分唯一索引。
|
||||||
|
--
|
||||||
|
-- 对应规格:docs/superpowers/specs/2026-09-20-ingest-idempotency-design.md §3.1–3.2
|
||||||
|
--
|
||||||
|
-- 幂等:ADD COLUMN / CREATE INDEX 全带 IF NOT EXISTS,可重复执行。
|
||||||
|
--
|
||||||
|
-- 应用后请重新导出结构:
|
||||||
|
-- ./bin/dbtool dump -clean -out db/backups/db_dump.sql
|
||||||
|
--
|
||||||
|
-- 注意:同规格 §3.6(month 列与「实体键并入 month」)**已作废**——
|
||||||
|
-- 由 docs/superpowers/specs/2026-09-21-duplicate-review-design.md §3.7 取代
|
||||||
|
-- (街拍实体键改为 (source, source_url),不再按月区分)。故本脚本**不建 month 列**。
|
||||||
|
|
||||||
|
-- 用 not null default '' 而不是可空:NULL 在唯一索引里不参与比较,
|
||||||
|
-- 会造成「同键可重复插入」的漏洞。
|
||||||
|
ALTER TABLE brand_runway_drafts ADD COLUMN IF NOT EXISTS source varchar(32) NOT NULL DEFAULT '';
|
||||||
|
ALTER TABLE brand_runway_drafts ADD COLUMN IF NOT EXISTS source_url varchar(512) NOT NULL DEFAULT '';
|
||||||
|
|
||||||
|
ALTER TABLE street_snap_drafts ADD COLUMN IF NOT EXISTS source varchar(32) NOT NULL DEFAULT '';
|
||||||
|
ALTER TABLE street_snap_drafts ADD COLUMN IF NOT EXISTS source_url varchar(512) NOT NULL DEFAULT '';
|
||||||
|
|
||||||
|
-- 两个部分唯一索引(全量唯一索引会因存量大量 ('','') 冲突而建索引失败)。
|
||||||
|
-- 向后兼容:老爬虫不上送 source_url 时该列为空串,自动被索引豁免 —— 行为与改动前一致。
|
||||||
|
CREATE UNIQUE INDEX IF NOT EXISTS uq_br_draft_source
|
||||||
|
ON brand_runway_drafts (source, source_url) WHERE source_url <> '';
|
||||||
|
CREATE UNIQUE INDEX IF NOT EXISTS uq_ss_draft_source
|
||||||
|
ON street_snap_drafts (source, source_url) WHERE source_url <> '';
|
||||||
1446
docs/superpowers/plans/2026-09-21-street-main-detail.md
Normal file
1446
docs/superpowers/plans/2026-09-21-street-main-detail.md
Normal file
File diff suppressed because it is too large
Load Diff
@ -118,9 +118,14 @@ source varchar(32) not null default ''
|
|||||||
source_url varchar(512) not null default ''
|
source_url varchar(512) not null default ''
|
||||||
```
|
```
|
||||||
|
|
||||||
对应模型:`internal/model/runway_draft.go` 的 `BrandRunwayDraft`、`internal/model/street_snap_draft.go` 的 `StreetSnapDraft`。列由 `AutoMigrate` 托管,**模型上不加 `uniqueIndex` tag**(GORM tag 无法表达部分索引条件)。
|
对应模型:`internal/model/runway_draft.go` 的 `BrandRunwayDraft`、`internal/model/street_snap_draft.go` 的 `StreetSnapDraft`。**模型上不加 `uniqueIndex` tag**(GORM tag 无法表达部分索引条件)。
|
||||||
|
|
||||||
索引写在 `internal/database/postgres.go` 的 `EnsureDedupSchema` 中——该函数本就是「`AutoMigrate` 之外的索引补充」的既定位置,且全部 `IF NOT EXISTS` 幂等:
|
> **落点已变更(2026-09-21)**:服务启动时的自动迁移(`AutoMigrate` / `EnsureDedupSchema`)已移除,
|
||||||
|
> 全库结构改由 `cmd/dbtool` 的 dump 维护。加列 / 加索引现在走 `db/migrations/` 下的一次性脚本:
|
||||||
|
> 对开发库执行 → 再 `dbtool dump -clean` 重新导出。本规格的列与索引已落在
|
||||||
|
> `db/migrations/2026-09-21-03-ingest-source-idempotency.sql`(已应用)。
|
||||||
|
|
||||||
|
索引定义(部分唯一索引——全量唯一索引会因存量大量 `('','')` 冲突而建索引失败):
|
||||||
|
|
||||||
```sql
|
```sql
|
||||||
CREATE UNIQUE INDEX IF NOT EXISTS uq_br_draft_source
|
CREATE UNIQUE INDEX IF NOT EXISTS uq_br_draft_source
|
||||||
|
|||||||
@ -117,7 +117,9 @@ CREATE INDEX IF NOT EXISTS idx_image_dups_owner
|
|||||||
|
|
||||||
**不冗余存对手的标题**:读时按 `peer_owner_kind` join 对应表取(草稿 → `*_drafts.title_en` / `.title`;正式 → `brand_runways.title_en` / `street_snaps.title`)。避免标题被改后出现陈旧副本。
|
**不冗余存对手的标题**:读时按 `peer_owner_kind` join 对应表取(草稿 → `*_drafts.title_en` / `.title`;正式 → `brand_runways.title_en` / `street_snaps.title`)。避免标题被改后出现陈旧副本。
|
||||||
|
|
||||||
建表放在 `internal/database/postgres.go` 的 `EnsureDedupSchema`(该函数本就是「`AutoMigrate` 之外的索引与表补充」的既定位置,且全部幂等)。
|
> **落点已变更(2026-09-21)**:`AutoMigrate` / `EnsureDedupSchema` 已移除,结构改由 `cmd/dbtool` 的 dump 维护。
|
||||||
|
> 本节的表与索引已落在 `db/migrations/2026-09-21-02-duplicate-review.sql`(已应用)。
|
||||||
|
> 今后加表 / 加索引一律走 `db/migrations/` 的一次性脚本 → 对开发库执行 → `dbtool dump -clean` 重新导出。
|
||||||
|
|
||||||
### 3.2 写入时机与算法
|
### 3.2 写入时机与算法
|
||||||
|
|
||||||
@ -226,7 +228,7 @@ CREATE UNIQUE INDEX IF NOT EXISTS uq_ss_source
|
|||||||
|
|
||||||
```
|
```
|
||||||
internal/model/image_duplicate.go 新增(模型)
|
internal/model/image_duplicate.go 新增(模型)
|
||||||
internal/database/postgres.go EnsureDedupSchema 建表与索引
|
db/migrations/2026-09-21-02-duplicate-review.sql 建表与索引(已应用)
|
||||||
internal/repository/dup_repository.go 新增:写入 + 读取 + 回填
|
internal/repository/dup_repository.go 新增:写入 + 读取 + 回填
|
||||||
internal/repository/ingest_repository.go StreetSnapIDByEntity 改键
|
internal/repository/ingest_repository.go StreetSnapIDByEntity 改键
|
||||||
internal/repository/review_repository.go SaveStreetSnapFromDraft / streetApprovedSiblingImages 改键
|
internal/repository/review_repository.go SaveStreetSnapFromDraft / streetApprovedSiblingImages 改键
|
||||||
|
|||||||
Reference in New Issue
Block a user