package recommod import ( "fmt" "time" "91porn-server/common/db" "91porn-server/common/log" "91porn-server/models" "91porn-server/models/v/vidmod" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo/options" ) var mdb, rdb *db.MongoDB const table = models.UserRecoRecord func coll(t *db.MongoTool) *db.MongoTool { if t == nil { return mdb.Coll(table) } return t.Coll(table) } func collRead() *db.MongoTool { return rdb.Coll(table) } // initIndex 设置index func initIndex() { many := []mongo.IndexModel{ //batch set indexes //value is the type 1 or -1 { Keys: bson.D{{Key: "uid", Value: 1}, {Key: "type", Value: 1}, {Key: "mark", Value: 1}}, Options: options.Index().SetUnique(true), }, } if _, err := coll(nil).CreateIndex(many); err != nil { panic(fmt.Sprintf("%s model set index err ==>[%+v]", table, err)) } } func insertRecoRecord(uid uint64, newsType string, typ string, mark string, line time.Time) error { now := time.Now() record := RecoRecord{ UID: uid, Type: typ, Mark: mark, TimeLine: line, UpdatedAt: now, CreatedAt: now, } if vidmod.IsSP(newsType) { record.TimeLine = line } if vidmod.IsCover(newsType) { record.CoverTimeLine = line } if _, err := coll(nil).InsertOne(&record); err != nil { log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "insertRecoRecord", table, "InsertOne", err), log.Any("uid", uid), log.Any("typ", typ), log.Any("mark", mark), log.Any("line", line), log.Any("newsType", newsType), ) return err } return nil } func updateRecoRecord(uid uint64, newsType string, typ string, mark string, line time.Time) (int64, error) { now := time.Now() cond := bson.M{"uid": uid, "type": typ, "mark": mark} update := bson.M{} if vidmod.IsSP(newsType) { update = bson.M{"$set": bson.M{"timeLine": line, "updatedAt": now}} } if vidmod.IsCover(newsType) { update = bson.M{"$set": bson.M{"coverTimeLine": line, "updatedAt": now}} } result, err := coll(nil).UpdateOne(cond, update) if err != nil { log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "updateRecoRecord", table, "UpdateOne", err), log.Any("uid", uid), log.Any("typ", typ), log.Any("mark", mark), log.Any("line", line), log.Any("newsType", newsType), ) } if result == nil { return 0, err } return result.MatchedCount, err } func findRecoRecord(uid uint64, typs []string) ([]RecoRecord, error) { var record []RecoRecord cond := bson.M{"uid": uid, "type": bson.M{"$in": typs}} if err := coll(nil).Find(&record, cond); err != nil { log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "findRecoRecord", table, "Find", err), log.Any("uid", uid), log.Any("typs", typs), ) return record, err } return record, nil } func findRecoRecordWithMark(uid uint64, typ string, marks []string) ([]RecoRecord, error) { var record []RecoRecord cond := bson.M{"uid": uid, "type": typ, "mark": bson.M{"$in": marks}} if err := collRead().Find(&record, cond); err != nil { log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "findRecoRecordWithMark", table, "Find", err), log.Any("uid", uid), log.Any("typ", typ), log.Any("marks", marks), ) return record, err } return record, nil } // SetRecoTimeLines 刷新维度的推荐时间轴 func SetRecoTimeLines(uid uint64, newsType string, set map[string]time.Time) error { for typ, line := range set { if line.IsZero() { continue } matchCnt, err := updateRecoRecord(uid, newsType, typ, "", line) if err != nil { return err } if matchCnt == 0 { if err = insertRecoRecord(uid, newsType, typ, "", line); err != nil { return err } } } return nil } // SetRecoTimeLinesWithMark 刷新维度的推荐时间轴 func SetRecoTimeLinesWithMark(uid uint64, newsType string, typ string, set map[string]time.Time) error { for mark, line := range set { if line.IsZero() { continue } matchCnt, err := updateRecoRecord(uid, newsType, typ, mark, line) if err != nil { return err } if matchCnt == 0 { if err = insertRecoRecord(uid, newsType, typ, mark, line); err != nil { return err } } } return nil } // GetRecoTimeLines 获取维度的推荐时间轴 func GetRecoTimeLines(uid uint64, newsType string, typs []string) (map[string]time.Time, error) { m := make(map[string]time.Time) records, err := findRecoRecord(uid, typs) for _, r := range records { if vidmod.IsSP(newsType) { m[r.Type] = ReviseTimeline(r.TimeLine) } if vidmod.IsCover(newsType) { m[r.Type] = ReviseTimeline(r.CoverTimeLine) } } return m, err } // GetRecoTimeLinesWithMark 获取维度的推荐时间轴 func GetRecoTimeLinesWithMark(uid uint64, newsType, typ string, marks []string) (map[string]time.Time, error) { m := make(map[string]time.Time) records, err := findRecoRecordWithMark(uid, typ, marks) for _, r := range records { if vidmod.IsSP(newsType) { m[r.Mark] = ReviseTimeline(r.TimeLine) } if vidmod.IsCover(newsType) { m[r.Mark] = ReviseTimeline(r.CoverTimeLine) } } return m, err } func ReviseTimeline(line time.Time) time.Time { tenMonthsBefore := time.Now().AddDate(0, -10, 0) if line.Before(tenMonthsBefore) || line.After(time.Now()) { return tenMonthsBefore } return line }