package followmod import ( "91porn-server/common/db" "91porn-server/common/log" "91porn-server/models" "fmt" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo/options" "time" ) var mdb *db.MongoDB const table = models.Follow func coll(t *db.MongoTool) *db.MongoTool { if t == nil { return mdb.Coll(table) } return t.Coll(table) } // initIndex 初始化索引 func initIndex() { many := []mongo.IndexModel{ { Keys: bson.D{{"followUID", -1}}, }, { Keys: bson.D{{"uid", 1}, {"followUID", 1}}, Options: options.Index().SetUnique(true), }, { Keys: bson.D{{"uniq", 1}}, }, { Keys: bson.D{{"createdAt", -1}}, }, } _, err := coll(nil).CreateIndex(many) if err != nil { panic(fmt.Sprintf("%s model set index err ==>[%+v]", table, err)) } return } // AddFollow 添加关注 func AddFollow(uid uint64, followUID uint64, isShort bool) (int64, error) { set := bson.M{"uniq": Unique(uid, followUID), "createdAt": time.Now()} if isShort { set["newsType"] = "SHORT" } res, err := coll(nil).UpsertOne( bson.M{"uid": uid, "followUID": followUID}, bson.M{"$set": set}) if err != nil { log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "AddFollow", table, "UpsertOne", err), log.Any("uid", uid), log.Any("followUID", followUID), ) } if res != nil { return res.UpsertedCount, err } return 0, err } // CloseFollow 取消关注 func CloseFollow(uid uint64, followUID uint64) (int64, error) { res, err := coll(nil).DeleteOne( bson.M{"uid": uid, "followUID": followUID}) if err != nil { log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "CloseFollow", table, "DeleteOne", err), log.Any("uid", uid), log.Any("followUID", followUID), ) } if res != nil { return res.DeletedCount, err } return 0, err } // IsFollow 是否关注 func IsFollow(uid uint64, followUID uint64) (bool, error) { f := FollowModel{} err := coll(nil).FindOne(&f, bson.M{"uid": uid, "followUID": followUID}) if err != nil { log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "IsFollow", table, "Count", err), log.Any("uid", uid), log.Any("followUID", followUID)) return false, err } if f.FollowUID == 0 { return false, err } return true, nil } // IsFollowUsers 是否关注这些用户 func IsFollowUsers(uid uint64, followUIDs []uint64) (map[uint64]bool, error) { if followUIDs == nil { followUIDs = []uint64{} } m := make(map[uint64]bool) if uid == 0 || len(followUIDs) == 0 { return m, nil } var infos []FollowModel err := coll(nil).Find(&infos, bson.M{"uid": uid, "followUID": bson.M{"$in": followUIDs}}) if err != nil { log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "IsFollowUsers", table, "Find", err), log.Any("uid", uid), log.Any("followUIDs", followUIDs), ) return m, err } for _, i := range infos { m[i.FollowUID] = true } return m, nil } // IsFollowedByUsers 是否被这些用户关注 func IsFollowedByUsers(followUID uint64, uids []uint64) (map[uint64]bool, error) { if uids == nil { uids = []uint64{} } m := make(map[uint64]bool) var infos []FollowModel err := coll(nil).Find(&infos, bson.M{"followUID": followUID, "uid": bson.M{"$in": uids}}) if err != nil { log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "IsFollowedByUsers", table, "Find", err), log.Any("followUID", followUID), log.Any("uids", uids), ) return m, err } for _, i := range infos { m[i.UID] = true } return m, nil } // FollowStatueMap 从给定的hash列表中获取like状态映射:hash->Statue // hash通过Vector.hash()获取 func FollowStatueMap(uniqList []string) (map[string]bool, error) { filter := bson.M{ "uniq": bson.M{"$in": uniqList}, } existLikeList := make([]FollowModel, 0, len(uniqList)) err := coll(nil).Find(&existLikeList, filter) if err != nil { log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "FollowStatueMap", table, "Find", err), log.Any("uniqList", uniqList), ) return nil, err } m := make(map[string]bool, len(existLikeList)) //初始化 for _, uniq := range uniqList { m[uniq] = false } //已经关注的 for _, v := range existLikeList { uniq := v.Uniq m[uniq] = true } return m, nil } // GetFollowCount 获取关注总数 func GetFollowCount(uid uint64) (int64, error) { total, err := coll(nil).Count(bson.M{"uid": uid}) if err != nil { log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "IsFollowEachOther", table, "Count", err), log.Any("uid", uid), ) return 0, err } return total, nil } // GetFansCount 获取粉丝总数 func GetFansCount(uid uint64) (int64, error) { total, err := coll(nil).Count(bson.M{"followUID": uid}) if err != nil { log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "GetFansCount", table, "Count", err), log.Any("uid", uid), ) return 0, err } return total, nil } // GetFollowList 获取关注列表 func GetFollowList(uid uint64, page int, size int, isShort bool) ([]uint64, map[uint64]FollowModel, bool, error) { hasNext := false m := make(map[uint64]FollowModel) cond := bson.M{"uid": uid} sort := bson.D{{Key: "createdAt", Value: -1}} opts := options.FindOptions{} opts.SetSort(sort).SetSkip(int64((page - 1) * size)).SetLimit(int64(size + 1)) if isShort { cond["newsType"] = "SHORT" } var data []*FollowModel err := coll(nil).Find(&data, cond, &opts) if err != nil { log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "GetFollowList", table, "Find", err), log.Any("uid", uid), log.Any("page", page), log.Any("size", size), ) return nil, m, false, err } if len(data) > size { hasNext = true data = data[:size] } var uids []uint64 for _, d := range data { if d == nil { continue } uids = append(uids, d.FollowUID) m[d.FollowUID] = *d } return uids, m, hasNext, nil } // GetFansList 获取粉丝列表 func GetFansList(uid uint64, page int, size int) ([]uint64, map[uint64]FollowModel, bool, error) { hasNext := false m := make(map[uint64]FollowModel) cond := bson.M{"followUID": uid} sort := bson.D{{Key: "createdAt", Value: -1}} opts := options.FindOptions{} opts.SetSort(sort).SetSkip(int64((page - 1) * size)).SetLimit(int64(size + 1)) var data []*FollowModel err := coll(nil).Find(&data, cond, &opts) if err != nil { log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "GetFansList", table, "Find", err), log.Any("uid", uid), log.Any("page", page), log.Any("size", size), ) return nil, m, hasNext, err } if len(data) > size { hasNext = true data = data[:size] } var uids []uint64 for _, d := range data { if d == nil { continue } uids = append(uids, d.UID) m[d.UID] = *d } return uids, m, hasNext, nil } // GetAllFansUid 获取所有粉丝用户id func GetAllFansUid(uid uint64) ([]uint64, error) { var data []*FollowModel cond := bson.M{"followUID": uid} sort := bson.D{{Key: "createdAt", Value: -1}} opts := options.FindOptions{} opts.SetSort(sort) err := coll(nil).Find(&data, cond, &opts) if err != nil { log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "GetAllFansUid", table, "Find", err), log.Any("uid", uid), ) return nil, err } var uids []uint64 for _, d := range data { uids = append(uids, d.UID) } return uids, nil } // GetTotalFollowList 获取所有关注用户 func GetTotalFollowList(uid uint64) ([]uint64, error) { var data []*FollowModel cond := bson.M{"uid": uid} sort := bson.D{{Key: "createdAt", Value: -1}} opts := options.FindOptions{} opts.SetSort(sort).SetLimit(5) err := coll(nil).Find(&data, cond, &opts) if err != nil { log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "GetTotalFollowList", table, "Find", err), log.Any("uid", uid), ) return nil, err } var uids []uint64 for _, d := range data { uids = append(uids, d.FollowUID) } return uids, nil } // GetTotalFollowListLimit 获取所有关注用户 func GetTotalFollowListLimit(uid uint64, limit int64) ([]uint64, error) { var data []*FollowModel cond := bson.M{"uid": uid} sort := bson.D{{Key: "createdAt", Value: -1}} opts := options.FindOptions{} opts.SetSort(sort).SetLimit(limit) err := coll(nil).Find(&data, cond, &opts) if err != nil { log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "GetTotalFollowListLimit", table, "Find", err), log.Any("uid", uid), ) return nil, err } var uids []uint64 for _, d := range data { uids = append(uids, d.FollowUID) } return uids, nil } // WeekFollowLeaderboard 周关注榜单 func WeekFollowLeaderboard(bind interface{}, filter bson.M, limit int) error { opt := options.Aggregate().SetAllowDiskUse(true) pip := []bson.M{ {"$match": filter}, // 过滤条件 由外部决定 {"$group": bson.M{"_id": "$followUID", "count": bson.M{"$sum": 1}}}, // 统计用户被关注 {"$sort": bson.M{"count": -1}}, // 按照作品数排序 {"$limit": limit}, // 限制返回条数 } return coll(nil).Aggregate(bind, pip, opt) }