This commit is contained in:
toom1996
2026-09-22 11:12:23 +08:00
parent 21dce13bde
commit d908036621
6 changed files with 1554 additions and 4 deletions

View 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;

View 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 <> '';

View 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 <> '';

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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 改键