package collectmod import ( "91porn-server/common/constant" "91porn-server/common/db" "91porn-server/common/log" "91porn-server/models" "91porn-server/models/commod" "fmt" "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" "time" ) var mdb *db.MongoDB var maxCollectTagsSize = 30 const table = models.Collect func coll(t *db.MongoTool) *db.MongoTool { if t == nil { return mdb.Coll(table) } return t.Coll(table) } // initCollectIndex 初始化索引 func initIndex() { many := []mongo.IndexModel{ { Keys: bson.D{{"uid", 1}, {"type", 1}}, }, { Keys: bson.D{{"uid", 1}, {"type", 1}, {"objID", 1}}, Options: options.Index().SetUnique(true), }, { Keys: bson.D{{"uniq", 1}}, Options: options.Index().SetUnique(true), }, } _, err := coll(nil).CreateIndex(many) if err != nil { panic(fmt.Sprintf("%s model set index err ==>[%+v]", table, err)) } return } // CollInsertOne 插入收藏消息记录 func CollInsertOne(c *Collect) (err error) { c.Uniq = Unique(c.UID, c.Type, c.ObjID) c.CreatedAt = time.Now() if _, err = coll(nil).InsertOne(c); err != nil { log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "CollInsertOne", table, "InsertOne", err)) return } return } // CollInsertMany 插入收藏消息记录 func CollInsertMany(c *[]Collect) (err error) { if _, err = coll(nil).InsertMany(c); err != nil { log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "CollInsertMany", table, "InsertMany", err)) return } return } // CollDeleteOne 取消收藏 func CollDeleteOne(uid uint64, cType string, objID primitive.ObjectID) (err error) { var query = bson.M{"uid": uid, "type": cType, "objID": objID} if _, err = coll(nil).DeleteOne(query); err != nil { log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "CollDeleteOne", table, "DeleteOne", err), log.Any("uid", uid), log.Any("cType", cType), log.Any("objID", objID), ) return } return } // CollDeleteMany 取消收藏 func CollDeleteMany(ids []string) (err error) { var query = bson.M{"uniq": bson.M{"$in": ids}} if _, err = coll(nil).DeleteMany(query); err != nil { log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "CollDeleteMany", table, "DeleteMany", err), log.Any("ids", ids), ) return } return } // CollFindOneByUidAndObjID 获取单条收藏信息 用于验证是否已经收藏 func CollFindOneByUidAndObjID(uid uint64, objID primitive.ObjectID) (data Collect, err error) { var query = bson.M{"uid": uid, "objID": objID} if err = coll(nil).FindOne(&data, query); err != nil { log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "CollFindOneByUidAndObjID", table, "FindOne", err), log.Any("uid", uid), log.Any("objID", objID), ) return } return } // CollFindOneByUidAndObjIds 获取多条收藏信息 用于验证是否已经收藏 func CollFindOneByUidAndObjIds(uid uint64, objIDS []primitive.ObjectID) (data []Collect, err error) { var query = bson.M{"uid": uid, "objID": bson.M{"$in": objIDS}} if err = coll(nil).Find(&data, query); err != nil { log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "CollFindOneByUidAndObjIds", table, "Find", err), log.Any("uid", uid), log.Any("objIDS", objIDS), ) return } return } // CollFindCollects 获取收藏列表 func CollFindCollects(uid uint64, cType string, stdQuery commod.StdQuery) (data []Collect, err error) { *stdQuery.Order = append(*stdQuery.Order, commod.OrderBy{Key: "createdAt", Desc: true}) var query = bson.M{"uid": uid, "type": cType} if err = coll(nil).Find(&data, query, commod.ConvertToListQuery(stdQuery)); err != nil { log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "CollFindOneByUidAndObjID", table, "FindOne", err), log.Any("uid", uid), log.Any("objID", cType), ) return } return } // CollFindCollectsByUIDAndObjIDs 获取包含指定对象收藏列表 func CollFindCollectsByUIDAndObjIDs(uid uint64, cType string, objIDs []primitive.ObjectID) (data []Collect, err error) { var query = bson.M{"uid": uid, "type": cType, "objID": bson.M{"$in": objIDs}} if err = coll(nil).Find(&data, query); err != nil { log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "CollFindOneByUidAndObjID", table, "FindOne", err), log.Any("uid", uid), log.Any("objID", cType), ) return } return } // CollFindCollectsByUIDAndObjId 获取包含指定对象收藏列表 func CollFindCollectsByUIDAndObjId(uid uint64, objId primitive.ObjectID) (data Collect, err error) { var query = bson.M{"uid": uid, "objID": objId} if err = coll(nil).FindOne(&data, query); err != nil { log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "CollFindCollectsByUIDAndObjId", table, "FindOne", err), log.Any("uid", uid), ) return } return } func QuickList(uid uint64, cType string, skip, limit int64) ([]Collect, int64, error) { filter := bson.M{"uid": uid, "type": cType} const maxLimit = 450 //iphone 11 一屏显示3项 1页3屏 1页9项 50页450项 opt := (&options.FindOptions{}).SetLimit(maxLimit) var totalList []Collect err := coll(nil).Find(&totalList, filter, opt) //取总共的数据 最多1000条 if err != nil { return nil, 0, err } total := int64(len(totalList)) if total == 0 { return []Collect{}, 0, nil } //内存中分页 skip + limit ∈ [0, total) if skip+limit > total { if skip > total { return []Collect{}, 0, nil } limit = total - skip } list := make([]Collect, 0, limit) for i := skip; i < skip+limit; i++ { list = append(list, totalList[i]) } return list, total, err } // CollFindCountByUID 获取收藏数量 func CollFindCountByUID(uid uint64) (data int64, err error) { data, err = coll(nil).Count(bson.M{"uid": uid}) if err != nil { log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "CollFindCountByUID", table, "Count", err), log.Any("uid", uid)) return } return } // CollFindCountByUidAndType 更具uid/type获取标签数量 func CollFindCountByUidAndType(uid uint64, cType string) (data int64, err error) { var query = bson.M{"uid": uid, "type": cType, "videoCount": bson.M{"$gt": 0}} if data, err = coll(nil).Count(query); err != nil { log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "CollFindCountByUidAndType", table, "Count", err), log.Any("uid", uid), log.Any("cType", cType), ) return } return } // CollFindCollectByTypeAndUID 我的收藏 func CollFindCollectByTypeAndUID(uid uint64, cType string) (cIDs []primitive.ObjectID, total int64, err error) { var opt options.FindOptions opt.SetSort(bson.M{"_id": -1}).SetLimit(4) query := bson.M{"uid": uid, "type": cType} var collects []*Collect if err = coll(nil).Find(&collects, query, &opt); err != nil { log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "CollFindCollectByTypeAndUID", table, "Find", err), log.Any("uid", uid), log.Any("cType", cType), ) return } for _, v := range collects { cIDs = append(cIDs, v.ObjID) } total, err = coll(nil).Count(query) if err != nil { log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "CollFindCollectByTypeAndUID", table, "Count", err), log.Any("uid", uid), log.Any("cType", cType), ) return } return } // CollIsExisted 是否收藏 func CollIsExisted(uid uint64, cType string, objID primitive.ObjectID) (isExists bool, err error) { cnt, err := coll(nil).Count(bson.M{"uid": uid, "type": cType, "objID": objID}) isExists = false if err != nil || cnt == 0 { return } isExists = true return } // 从给定的uniq列表中获取收藏状态映射:uniq->Statue // uniq通过uniq()获取 func CltStatueMap(uniqList []string) (map[string]bool, error) { if len(uniqList) == 0 { return make(map[string]bool), nil } filter := bson.M{ "uniq": bson.M{"$in": uniqList}, } existCltList := make([]Collect, 0, len(uniqList)) err := coll(nil).Find(&existCltList, filter) if err != nil { return nil, err } m := make(map[string]bool, len(existCltList)) //初始化 for _, uniq := range uniqList { m[uniq] = false } //已经收藏的 for _, v := range existCltList { m[v.Uniq] = true } return m, nil } // IsCollectVideos 是否收藏视频 func IsCollectVideos(uid uint64, videoIDs []primitive.ObjectID) (map[primitive.ObjectID]bool, error) { m := make(map[primitive.ObjectID]bool) videoIDs = uniqueVideoIDs(videoIDs) if len(videoIDs) == 0 { return m, nil } var infos []Collect query := collectVideoStatusFilter(uid, videoIDs) opts := options.Find().SetProjection(bson.M{"_id": 0, "objID": 1}) if err := coll(nil).Find(&infos, query, opts); err != nil { log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "IsCollectVideos", table, "Find", err), log.Any("uid", uid), log.Any("videoIDs", videoIDs), ) return m, err } for _, i := range infos { m[i.ObjID] = true } return m, nil } func collectVideoStatusFilter(uid uint64, videoIDs []primitive.ObjectID) bson.M { return bson.M{ "uid": uid, "type": bson.M{"$in": []string{ constant.CollectTypeSP, constant.CollectTypeShort, constant.CollectTypeCover, constant.CollectTypePIC, constant.CollectTypeSEED_LINK, constant.CollectTypeAiPlaza, }}, "objID": bson.M{"$in": videoIDs}, } } func uniqueVideoIDs(ids []primitive.ObjectID) []primitive.ObjectID { if len(ids) < 2 { return ids } seen := make(map[primitive.ObjectID]struct{}, len(ids)) unique := make([]primitive.ObjectID, 0, len(ids)) for _, id := range ids { if _, ok := seen[id]; ok { continue } seen[id] = struct{}{} unique = append(unique, id) } return unique } // GetLocsCollectCnt2Map 获取位置的收藏数 func GetLocsCollectCnt2Map(locIDs []primitive.ObjectID) (map[primitive.ObjectID]int, error) { if locIDs == nil { locIDs = []primitive.ObjectID{} } m := make(map[primitive.ObjectID]int) var data []CityCount p := []bson.M{ {"$match": bson.M{"type": constant.CollectTypeLocation, "objID": bson.M{"$in": locIDs}}}, {"$group": bson.M{"_id": "$objID", "count": bson.M{"$sum": 1}}}, } if err := coll(nil).Aggregate(&data, p); err != nil { log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "GetLocsCollectCnt2Map", table, "Aggregate", err), log.Any("locIDs", locIDs)) return nil, err } for _, d := range data { m[d.ID] = d.Count } return m, nil } // MyCollectTags 获取收藏标签 func MyCollectTags(uid uint64, top int) ([]primitive.ObjectID, error) { var ids []primitive.ObjectID stdQuery := commod.StdQuery{Page: &commod.PageBy{Num: 1, Size: uint64(top)}, Order: &[]commod.OrderBy{}} data, err := CollFindCollects(uid, constant.CollectTypeTag, stdQuery) if err != nil { return ids, nil } for _, d := range data { ids = append(ids, d.ObjID) } return ids, nil } // 根据标签id获取收藏列表 func GetCollectTagList(uid uint64, tagsID []primitive.ObjectID) (data []Collect, err error) { if tagsID == nil || uid == 0 { return } var query = bson.M{ "uid": uid, "type": constant.CollectTypeTag, "objID": bson.M{"$in": tagsID}, } err = coll(nil).Find(&data, query) if err != nil { log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "GetCollectTagList", table, "Find", err), log.Any("uid", uid), log.Any("tagsID", tagsID), ) return } return }