update
This commit is contained in:
75
scripts/backfill_title_cn/main.go
Normal file
75
scripts/backfill_title_cn/main.go
Normal file
@ -0,0 +1,75 @@
|
||||
// Command backfill_title_cn 把 brand_runway.title_cn 由已解析的结构化分类字段
|
||||
// (year / collection_type / season)规则生成中文走秀标题。
|
||||
//
|
||||
// 设计:
|
||||
// - title 字段本质就是「季节/品类描述」(Vogue 格式:Spring 2026 Ready-to-Wear、
|
||||
// Resort 2026、Pre-Fall 2023、Fall 2023 Couture、Spring 2024 Menswear),
|
||||
// 品牌名在 JOIN 出的 brand_name 里单独给,不混进 title。
|
||||
// - collection_type / season 早已由历史迁移解析回填,因此 title_cn 可纯规则生成,
|
||||
// 完全不依赖外部翻译服务,且结果稳定可重跑。
|
||||
//
|
||||
// 幂等:每次都按分类字段重新计算并整表覆盖,重跑无害。
|
||||
// 不写任何业务逻辑,仅做一次性数据回填。
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
|
||||
"gorm.io/driver/mysql"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
const dsn = "root:root@tcp(127.0.0.1:3306)/db?charset=utf8mb4&parseTime=True&loc=Local"
|
||||
|
||||
// titleCnSQL 单条 UPDATE 用 CASE 把分类字段映射为中文标题。
|
||||
// year 参与拼接(CONCAT),season 为 NULL 时 COALESCE 成 ''。
|
||||
const titleCnSQL = `
|
||||
UPDATE brand_runway
|
||||
SET title_cn = CASE
|
||||
WHEN collection_type = 'resort' THEN CONCAT(year, ' 度假系列')
|
||||
WHEN collection_type = 'pre_fall' THEN CONCAT(year, ' 早秋系列')
|
||||
WHEN collection_type = 'rtw' AND season = 'spring' THEN CONCAT(year, ' 春夏成衣')
|
||||
WHEN collection_type = 'rtw' AND season = 'fall' THEN CONCAT(year, ' 秋冬成衣')
|
||||
WHEN collection_type = 'rtw' THEN CONCAT(year, ' 成衣')
|
||||
WHEN collection_type = 'menswear' AND season = 'spring' THEN CONCAT(year, ' 春夏男装')
|
||||
WHEN collection_type = 'menswear' AND season = 'fall' THEN CONCAT(year, ' 秋冬男装')
|
||||
WHEN collection_type = 'couture' AND season = 'spring' THEN CONCAT(year, ' 春夏高定')
|
||||
WHEN collection_type = 'couture' AND season = 'fall' THEN CONCAT(year, ' 秋冬高定')
|
||||
ELSE CONCAT(year, ' 系列')
|
||||
END
|
||||
WHERE is_deleted = 0`
|
||||
|
||||
func main() {
|
||||
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
|
||||
if err != nil {
|
||||
log.Fatal("open:", err)
|
||||
}
|
||||
|
||||
var before int64
|
||||
db.Raw(`SELECT COUNT(*) FROM brand_runway WHERE is_deleted=0 AND title_cn <> ''`).Scan(&before)
|
||||
fmt.Printf("before: title_cn 非空 = %d\n", before)
|
||||
|
||||
if r := db.Exec(titleCnSQL); r.Error != nil {
|
||||
log.Fatalf("backfill title_cn failed: %v", r.Error)
|
||||
} else {
|
||||
fmt.Printf("updated rows = %d\n", r.RowsAffected)
|
||||
}
|
||||
|
||||
var after int64
|
||||
db.Raw(`SELECT COUNT(*) FROM brand_runway WHERE is_deleted=0 AND title_cn <> ''`).Scan(&after)
|
||||
fmt.Printf("after: title_cn 非空 = %d\n", after)
|
||||
|
||||
// 抽样核对:原始 title -> 生成 title_cn
|
||||
type row struct {
|
||||
Title string
|
||||
TitleCn string
|
||||
}
|
||||
var rows []row
|
||||
db.Raw(`SELECT title, title_cn FROM brand_runway WHERE is_deleted=0 ORDER BY id LIMIT 12`).Scan(&rows)
|
||||
fmt.Println("samples:")
|
||||
for _, r := range rows {
|
||||
fmt.Printf(" %-32q -> %q\n", r.Title, r.TitleCn)
|
||||
}
|
||||
fmt.Println("title_cn backfill done.")
|
||||
}
|
||||
54
scripts/diag_brand/main.go
Normal file
54
scripts/diag_brand/main.go
Normal file
@ -0,0 +1,54 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"gorm.io/driver/mysql"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
const dsn = "root:root@tcp(127.0.0.1:3306)/db?charset=utf8mb4&parseTime=True&loc=Local"
|
||||
|
||||
func main() {
|
||||
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// 1) brand 3100 的走秀档案数(only_with_articles 子查询依赖这个)
|
||||
var artCount int64
|
||||
db.Raw(`SELECT COUNT(*) FROM brand_runway WHERE is_deleted=0 AND brand_id=3100`).Scan(&artCount)
|
||||
fmt.Printf("brand 3100 走秀档案数 = %d\n", artCount)
|
||||
|
||||
// 2) 复现后端完整搜索:only_with_articles=1 + keyword=猿人头
|
||||
kw := "%猿人头%"
|
||||
type Row struct {
|
||||
ID uint32
|
||||
Name string
|
||||
NameEn string
|
||||
NameCn string
|
||||
}
|
||||
var rows []Row
|
||||
db.Raw(`
|
||||
SELECT id, name, name_en, name_cn FROM brand
|
||||
WHERE is_deleted=0
|
||||
AND id IN (SELECT DISTINCT brand_id FROM brand_runway WHERE is_deleted=0)
|
||||
AND (name_en LIKE ? OR name_cn LIKE ?)`,
|
||||
kw, kw).Scan(&rows)
|
||||
fmt.Printf("\n[搜索 keyword=猿人头, only_with_articles=1] 命中 %d 条:\n", len(rows))
|
||||
for _, r := range rows {
|
||||
fmt.Printf(" id=%d | name=%q | name_en=%q | name_cn=%q\n", r.ID, r.Name, r.NameEn, r.NameCn)
|
||||
}
|
||||
|
||||
// 3) 对比:only_with_articles=0(不过滤档案)时的命中
|
||||
var rows2 []Row
|
||||
db.Raw(`
|
||||
SELECT id, name, name_en, name_cn FROM brand
|
||||
WHERE is_deleted=0
|
||||
AND (name_en LIKE ? OR name_cn LIKE ?)`,
|
||||
kw, kw).Scan(&rows2)
|
||||
fmt.Printf("\n[搜索 keyword=猿人头, only_with_articles=0] 命中 %d 条:\n", len(rows2))
|
||||
for _, r := range rows2 {
|
||||
fmt.Printf(" id=%d | name=%q | name_en=%q | name_cn=%q\n", r.ID, r.Name, r.NameEn, r.NameCn)
|
||||
}
|
||||
}
|
||||
68
scripts/diag_hot/main.go
Normal file
68
scripts/diag_hot/main.go
Normal file
@ -0,0 +1,68 @@
|
||||
package main
|
||||
|
||||
// 诊断:复现 FeaturedIDs("images", 30) 的 SQL,验证热门品牌排名数据是否合理。
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"gorm.io/driver/mysql"
|
||||
"gorm.io/gorm"
|
||||
)
|
||||
|
||||
const dsn = "root:root@tcp(127.0.0.1:3306)/db?charset=utf8mb4&parseTime=True&loc=Local"
|
||||
|
||||
func main() {
|
||||
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// 1) 复现 FeaturedIDs:按图片总数 DESC 取前 30
|
||||
type Row struct {
|
||||
BrandID uint32 `gorm:"column:brand_id"`
|
||||
Images int64 `gorm:"column:images"`
|
||||
Shows int64 `gorm:"column:shows"`
|
||||
}
|
||||
var rows []Row
|
||||
db.Raw(`
|
||||
SELECT brand_id, COALESCE(SUM(image_count),0) AS images, COUNT(*) AS shows
|
||||
FROM brand_runway
|
||||
WHERE is_deleted = 0
|
||||
GROUP BY brand_id
|
||||
ORDER BY images DESC
|
||||
LIMIT 30
|
||||
`).Scan(&rows)
|
||||
|
||||
fmt.Println("== FeaturedIDs(images, 30) 原始排名 ==")
|
||||
for i, r := range rows {
|
||||
var name string
|
||||
db.Raw(`SELECT name_en FROM brand WHERE id = ?`, r.BrandID).Scan(&name)
|
||||
fmt.Printf("%2d. brand_id=%-6d images=%-6d shows=%-4d %s\n", i+1, r.BrandID, r.Images, r.Shows, name)
|
||||
}
|
||||
|
||||
// 2) image_count 分布:有多少品牌有图、多少归零
|
||||
var zeroBrands, hasImgBrands int64
|
||||
var totalRows, zeroRows int64
|
||||
db.Raw(`SELECT COUNT(*) FROM (SELECT brand_id, SUM(image_count) s FROM brand_runway WHERE is_deleted=0 GROUP BY brand_id) t WHERE s = 0`).Scan(&zeroBrands)
|
||||
db.Raw(`SELECT COUNT(*) FROM (SELECT brand_id, SUM(image_count) s FROM brand_runway WHERE is_deleted=0 GROUP BY brand_id) t WHERE s > 0`).Scan(&hasImgBrands)
|
||||
db.Raw(`SELECT COUNT(*) FROM brand_runway WHERE is_deleted=0`).Scan(&totalRows)
|
||||
db.Raw(`SELECT COUNT(*) FROM brand_runway WHERE is_deleted=0 AND image_count=0`).Scan(&zeroRows)
|
||||
fmt.Printf("\n== image_count 分布 ==\n有图品牌=%d 零图品牌=%d | 走秀总行=%d 其中 image_count=0 的行=%d\n", hasImgBrands, zeroBrands, totalRows, zeroRows)
|
||||
|
||||
// 3) 对比口径:按走秀数(shows) DESC 前 10
|
||||
var byShows []Row
|
||||
db.Raw(`
|
||||
SELECT brand_id, COALESCE(SUM(image_count),0) AS images, COUNT(*) AS shows
|
||||
FROM brand_runway
|
||||
WHERE is_deleted = 0
|
||||
GROUP BY brand_id
|
||||
ORDER BY shows DESC
|
||||
LIMIT 10
|
||||
`).Scan(&byShows)
|
||||
fmt.Println("\n== 若按 shows DESC 前 10 ==")
|
||||
for i, r := range byShows {
|
||||
var name string
|
||||
db.Raw(`SELECT name_en FROM brand WHERE id = ?`, r.BrandID).Scan(&name)
|
||||
fmt.Printf("%2d. brand_id=%-6d images=%-6d shows=%-4d %s\n", i+1, r.BrandID, r.Images, r.Shows, name)
|
||||
}
|
||||
}
|
||||
@ -47,3 +47,33 @@ UPDATE brand_runway SET
|
||||
description_en = description,
|
||||
title_cn = '',
|
||||
description_cn = '';
|
||||
|
||||
-- ============================================================================
|
||||
-- 第 5 步(依赖「分类字段回填迁移」之后执行):title_cn 规则生成
|
||||
--
|
||||
-- 前提:collection_type / season / year 已由历史迁移解析回填(rtw/menswear/
|
||||
-- couture/resort/pre_fall × spring/fall/空)。title 本质是「季节/品类描述」,
|
||||
-- 品牌名在 JOIN 的 brand_name 里单独给,因此 title_cn 可纯规则生成,
|
||||
-- 完全不依赖外部翻译服务,结果稳定可重跑。
|
||||
--
|
||||
-- 映射:resort→「{year} 度假系列」、pre_fall→「{year} 早秋系列」、
|
||||
-- rtw→「{year} {春夏|秋冬}成衣」、menswear→「{year} {春夏|秋冬}男装」、
|
||||
-- couture→「{year} {春夏|秋冬}高定」。
|
||||
--
|
||||
-- 执行器:scripts/backfill_title_cn/main.go(幂等,整表覆盖重跑无害)。
|
||||
-- 该步骤与上方 i18n 加列/回填相互独立,可单独重跑。
|
||||
-- ============================================================================
|
||||
UPDATE brand_runway
|
||||
SET title_cn = CASE
|
||||
WHEN collection_type = 'resort' THEN CONCAT(year, ' 度假系列')
|
||||
WHEN collection_type = 'pre_fall' THEN CONCAT(year, ' 早秋系列')
|
||||
WHEN collection_type = 'rtw' AND season = 'spring' THEN CONCAT(year, ' 春夏成衣')
|
||||
WHEN collection_type = 'rtw' AND season = 'fall' THEN CONCAT(year, ' 秋冬成衣')
|
||||
WHEN collection_type = 'rtw' THEN CONCAT(year, ' 成衣')
|
||||
WHEN collection_type = 'menswear' AND season = 'spring' THEN CONCAT(year, ' 春夏男装')
|
||||
WHEN collection_type = 'menswear' AND season = 'fall' THEN CONCAT(year, ' 秋冬男装')
|
||||
WHEN collection_type = 'couture' AND season = 'spring' THEN CONCAT(year, ' 春夏高定')
|
||||
WHEN collection_type = 'couture' AND season = 'fall' THEN CONCAT(year, ' 秋冬高定')
|
||||
ELSE CONCAT(year, ' 系列')
|
||||
END
|
||||
WHERE is_deleted = 0;
|
||||
|
||||
Reference in New Issue
Block a user