From ed51664a09edeeafd0355a64521a06759a113663 Mon Sep 17 00:00:00 2001 From: root Date: Thu, 29 Oct 2026 20:24:38 +0800 Subject: [PATCH] =?UTF-8?q?[AI]=20fix:=20=E5=89=A7=E9=9B=86=E5=8E=BB?= =?UTF-8?q?=E9=87=8D=E9=94=AE=E8=A1=A5=E4=B8=8A=20videoUrl?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 媒资库会给同一集重新发 hashId(「JK学姐不为人知的秘密」源库那条 hashId 6aa23652…、本地那条 6acaf74c…,videoUrl 一模一样), 只比 hashId 会漏掉这一类重复,前端仍显示「1 1 2 2」。 改成 mediaId 下 hashId 或 videoUrl 任一相同即认定是同一集。 Co-Authored-By: Claude Opus 5 (1M context) --- scripts/contentsync/main.go | 66 +++++++++++++++++++++++-------------- 1 file changed, 42 insertions(+), 24 deletions(-) diff --git a/scripts/contentsync/main.go b/scripts/contentsync/main.go index 39d0a84..8fbaf87 100644 --- a/scripts/contentsync/main.go +++ b/scripts/contentsync/main.go @@ -261,8 +261,8 @@ func runPass(ctx context.Context, srcDB *mongo.Database, t target, spec CollSpec return out, c.Err() } - // localTwins 查出这批源文档在目标库的「同一集另一条」: - // (mediaId, hashId) 相同但 _id 不同。 + // localTwins 查出这批源文档在目标库的「同一集另一条」:同属一个 mediaId, + // 且 hashId 或 videoUrl 相同,但 _id 不同。 // // 各站点自己也在跑媒资库同步(common/media/syncMedia.go),它按 // (mediaId, hashId) 去重、用自己的 _id 为同一集插一条;本同步再把源库那条 @@ -270,29 +270,40 @@ func runPass(ctx context.Context, srcDB *mongo.Database, t target, spec CollSpec // 更要紧的是媒资库那条在 SaleCoin=0 时 listenPermission=2(免费), // 等于用户可以白看本该收费的集。 // + // 必须同时认 videoUrl:媒资库会给同一集重新发 hashId(实测 + // 「JK学姐不为人知的秘密」源库那条 hashId 6aa23652…、本地那条 + // 6acaf74c…,videoUrl 却一模一样),只比 hashId 会漏掉这一类。 + // // 以源库那条为准(购买记录都挂在它上面),把本地那条下架 isActive:false, // 不删除,便于事后回查。 localTwins := func(docs []bson.M) (map[any]any, error) { - hashes := make([]any, 0, len(docs)) - want := map[string]any{} // mediaId|hashId -> 源库 _id - for _, d := range docs { - h, ok := d["hashId"].(string) - if !ok || h == "" { - continue + keys := make([]any, 0, len(docs)*2) // 待查的 hashId 与 videoUrl + want := map[string]any{} // mediaId|key -> 源库 _id + add := func(mid primitive.ObjectID, v string, id any) { + if v == "" { + return } + keys = append(keys, v) + want[mid.Hex()+"|"+v] = id + } + for _, d := range docs { mid, ok := d["mediaId"].(primitive.ObjectID) if !ok { continue } - hashes = append(hashes, h) - want[mid.Hex()+"|"+h] = d["_id"] + h, _ := d["hashId"].(string) + u, _ := d["videoUrl"].(string) + add(mid, h, d["_id"]) + add(mid, u, d["_id"]) } - if len(hashes) == 0 { + if len(keys) == 0 { return nil, nil } - // hashId 上有索引,按它捞再在内存里配 mediaId - c, e := dst.Find(ctx, bson.M{"hashId": bson.M{"$in": hashes}, "isActive": true}, - options.Find().SetProjection(bson.M{"_id": 1, "mediaId": 1, "hashId": 1})) + // hashId 上有索引;videoUrl 没有,所以放在同一个 $or 里一次查完 + c, e := dst.Find(ctx, bson.M{"isActive": true, "$or": []bson.M{ + {"hashId": bson.M{"$in": keys}}, + {"videoUrl": bson.M{"$in": keys}}, + }}, options.Find().SetProjection(bson.M{"_id": 1, "mediaId": 1, "hashId": 1, "videoUrl": 1})) if e != nil { return nil, e } @@ -300,21 +311,28 @@ func runPass(ctx context.Context, srcDB *mongo.Database, t target, spec CollSpec out := map[any]any{} for c.Next(ctx) { var row struct { - ID primitive.ObjectID `bson:"_id"` - MediaID primitive.ObjectID `bson:"mediaId"` - HashID string `bson:"hashId"` + ID primitive.ObjectID `bson:"_id"` + MediaID primitive.ObjectID `bson:"mediaId"` + HashID string `bson:"hashId"` + VideoURL string `bson:"videoUrl"` } if e := c.Decode(&row); e != nil { return nil, e } - srcID, ok := want[row.MediaID.Hex()+"|"+row.HashID] - if !ok { - continue + for _, k := range []string{row.HashID, row.VideoURL} { + if k == "" { + continue + } + srcID, ok := want[row.MediaID.Hex()+"|"+k] + if !ok { + continue + } + if sid, ok := srcID.(primitive.ObjectID); ok && sid == row.ID { + continue // 就是源库那条自己,不是重复 + } + out[srcID] = row.ID + break } - if sid, ok := srcID.(primitive.ObjectID); ok && sid == row.ID { - continue // 就是源库那条自己,不是重复 - } - out[srcID] = row.ID } return out, c.Err() }