package hotvalue import ( "91porn-server/common/log" "91porn-server/models/v/cmtmod" "91porn-server/models/v/mediamod" "91porn-server/models/v/vidmod" "github.com/golang-module/carbon/v2" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/bson/primitive" "go.mongodb.org/mongo-driver/mongo" "math" "time" ) type updateFn func(models []mongo.WriteModel) error var ( actions = map[string]updateFn{ cmtmod.OTypeVideo: vidmod.Bulk, cmtmod.OTypeCartoon: mediamod.Bulk, } ) // ResetHot 重置热度值 func ResetHot() { start := carbon.NewCarbon().SubDays(30).StdTime() end := time.Now() writes := make([]mongo.WriteModel, 0) for objType, fn := range actions { skip := 0 limit := 100 for { // 获取30天内有评论的objID objIds, hasNext, err := cmtmod.GetObjIdsBetweenTime(objType, start, end, skip, limit) if err != nil { log.Error("Job ResetHot cmtmod.GetObjIdsBetweenTime fail", log.E(err)) return } for _, objId := range objIds { hotData := resetObjectHot(objId, objType, start, end) if len(hotData) == 0 { continue } update := mongo.NewUpdateOneModel().SetFilter(bson.M{"_id": objId}).SetUpdate(hotData).SetUpsert(true) writes = append(writes, update) } if len(writes) > 0 { err = fn(writes) if err != nil { log.Error("Job ResetHot fail", log.E(err), log.Any("objType", objType), log.Any("skip", skip)) } } writes = writes[0:0] skip = skip + limit if !hasNext { break } } } } // 热度=Z历史所有评论数 × 30% × e^(−{评论天数}×0.1) //+Z近7天评论数 × 70% func resetObjectHot(objId primitive.ObjectID, objType string, start, end time.Time) bson.M { // 暂时只支持视频和ACG的评论 if objType != cmtmod.OTypeVideo && objType != cmtmod.OTypeCartoon { return nil } // 获取该对性一段时间内,按天分组,每天的评论总数 list, err := cmtmod.GetCountGroupByDay(objId, start, end) if err != nil { log.Error("Job ResetHot resetObjectHot cmtmod.GetCountGroupByDay fail", log.E(err)) return nil } var historyHot float64 var sevenDayCount float64 // 计算出该对象的热度值 for _, v := range list { // 获取跟今天相差的天数 day := float64(carbon.Now().DiffAbsInDays(carbon.ParseByFormat(v.Time, "Y-m-d"))) // 计算历史评论热度 hot := calculateCommentScore(v.Count, day) historyHot = historyHot + hot // 累加近七天的总数 if day <= 7 { sevenDayCount = sevenDayCount + float64(v.Count) } } currentHot := historyHot + sevenDayCount*0.7 log.Info("Job ResetHot resetObjectHot result", log.Any("hot", currentHot)) data := bson.M{"hot": currentHot} if objType == cmtmod.OTypeVideo { data["updatedAt"] = time.Now() } else { data["updateTime"] = time.Now() } return bson.M{"$set": data} } func calculateCommentScore(totalComments int64, daysSinceComment float64) float64 { // Ensure we don't have negative days if daysSinceComment < 0 { daysSinceComment = 0 } // Calculate the decay factor: e^(-days * 0.1) decayFactor := math.Exp(-daysSinceComment * 0.1) // Calculate the final score: totalComments * 0.3 * decayFactor score := float64(totalComments) * 0.3 * decayFactor return score }