package hotstatmod import ( "fmt" "time" "91porn-server/common/db" "91porn-server/common/log" "91porn-server/common/timeutil/timerange" "91porn-server/models" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/bson/primitive" "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo/options" ) var mdb *db.MongoDB const table = models.NewsHot func coll(t *db.MongoTool) *db.MongoTool { if t == nil { return mdb.Coll(table) } return t.Coll(table) } // InitIndex 设置index func initIndex() { many := []mongo.IndexModel{ { Keys: bson.D{{Key: "sumDate", Value: 1}, {Key: "videoID", Value: 1}}, Options: options.Index(), }, { Keys: bson.D{{Key: "sumDate", Value: 1}, {Key: "todayHot", Value: -1}}, Options: options.Index(), }, { Keys: bson.D{{Key: "sumDate", Value: 1}, {Key: "weekHot", Value: -1}}, Options: options.Index(), }, { Keys: bson.D{{Key: "sumDate", Value: 1}, {Key: "monthHot", Value: -1}}, Options: options.Index(), }, { Keys: bson.D{{Key: "createdAt", Value: 1}}, Options: options.Index(), }, } if _, err := coll(nil).CreateIndex(many); err != nil { panic(fmt.Sprintf("%s model set index err ==>[%+v]", table, err)) } } // UpdateInsertHotValue 更新热度数值,没有就插入 func UpdateInsertHotValue(sumDate time.Time, mDayli map[primitive.ObjectID]int, mWeek map[primitive.ObjectID]int, mMonth map[primitive.ObjectID]int, mNow map[primitive.ObjectID]int) error { writes := make([]mongo.WriteModel, len(mNow)) i := 0 for vid, v := range mNow { filter := bson.M{ "sumDate": sumDate, "videoID": vid, } update := bson.M{ "$setOnInsert": bson.M{ "sumDate": sumDate, "videoID": vid, "createdAt": time.Now(), }, "$set": bson.M{ "todayHot": mDayli[vid], "weekHot": mWeek[vid], "monthHot": mMonth[vid], "totalHot": v, "updatedAt": time.Now(), }, } writes[i] = mongo.NewUpdateOneModel().SetFilter(filter).SetUpdate(update).SetUpsert(true) i++ log.Debug(fmt.Sprintf("sumDate:%s table:%s [filter:%+v update:%+v ]\n", sumDate, table, filter, update)) } if len(writes) == 0 { return nil } //bulkWrite 不是原子操作 不具备事务性 opt := (&options.BulkWriteOptions{}).SetOrdered(false) //设为无序,触发并行写,提升写效率 _, err := coll(nil).Bulk(writes, opt) return err } func getHotValue(page, size uint64, cond bson.M, sort bson.D) ([]*HotStat, bool, error) { hasNext := false skip := (page - 1) * size opts := options.FindOptions{} if sort != nil { opts.SetSort(sort) } opts.SetSkip(int64(skip)).SetLimit(int64(size + 1)) var back []*HotStat if err := coll(nil).Find(&back, cond, &opts); err != nil { log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "getHotValue", table, "Find", err), log.Any("page", page), log.Any("size", size), log.Any("cond", cond), log.Any("sort", sort), ) return nil, hasNext, err } if uint64(len(back)) > size { hasNext = true back = back[:size] } return back, hasNext, nil } func getSortedVideoID(page, size uint64, cond bson.M, sort bson.D) ([]primitive.ObjectID, bool, error) { ids := []primitive.ObjectID{} infos, hasNext, err := getHotValue(page, size, cond, sort) if err != nil { return ids, false, err } ids = make([]primitive.ObjectID, len(infos)) for i, v := range infos { ids[i] = v.VideoID } return ids, hasNext, err } // GetHotValueToday 查找热度值 func GetHotValueToday(page, size uint64) ([]primitive.ObjectID, bool, error) { sumDate := timerange.LocDayRange(time.Now()).Head cond := bson.M{"sumDate": sumDate} sort := bson.D{{Key: "todayHot", Value: -1}} return getSortedVideoID(page, size, cond, sort) } // GetHotValueWeek 查找热度值 func GetHotValueWeek(page, size uint64) ([]primitive.ObjectID, bool, error) { sumDate := timerange.LocDayRange(time.Now()).Head cond := bson.M{"sumDate": sumDate} sort := bson.D{{Key: "weekHot", Value: -1}} return getSortedVideoID(page, size, cond, sort) } // GetHotValueMonth 查找热度值 func GetHotValueMonth(page, size uint64) ([]primitive.ObjectID, bool, error) { sumDate := timerange.LocDayRange(time.Now()).Head cond := bson.M{"sumDate": sumDate} sort := bson.D{{Key: "monthHot", Value: -1}} return getSortedVideoID(page, size, cond, sort) } func getHotValueByDate(dt time.Time) (map[primitive.ObjectID]int, error) { var infos []*HotStat mValue := make(map[primitive.ObjectID]int) if err := coll(nil).Find(&infos, bson.M{"sumDate": dt}); err != nil { log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "getHotValue", table, "Find", err)) return mValue, err } for _, v := range infos { mValue[v.VideoID] = v.TotalHot } return mValue, nil } // GetYesterdayHotValue 获取昨日热度值 func GetYesterdayHotValue(dt time.Time) (map[primitive.ObjectID]int, error) { return getHotValueByDate(dt.AddDate(0, 0, -1)) } // GetLastWeekHotValue 获取上个周日热度值 func GetLastWeekHotValue(dt time.Time) (map[primitive.ObjectID]int, error) { offset := 0 wk := dt.Weekday() switch wk { case time.Monday: offset = -1 case time.Tuesday: offset = -2 case time.Wednesday: offset = -3 case time.Thursday: offset = -4 case time.Friday: offset = -5 case time.Saturday: offset = -6 } return getHotValueByDate(dt.AddDate(0, 0, offset)) } // GetLastMonthHotValue 获取上个月末热度值 func GetLastMonthHotValue(dt time.Time) (map[primitive.ObjectID]int, error) { return getHotValueByDate(dt.AddDate(0, 0, -dt.Day())) } func DeleteBeforeCreatedAt(t *db.MongoTool, tm time.Time) error { _, err := coll(t).DeleteMany(bson.M{"createdAt": bson.M{"$lt": tm}}) return err }