package likemod import ( "fmt" "time" "91porn-server/common/constant" "91porn-server/common/db" "91porn-server/common/log" "91porn-server/models" "go.mongodb.org/mongo-driver/bson/primitive" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo/options" ) var mdb *db.MongoDB const table = models.Like func coll(t *db.MongoTool) *db.MongoTool { if t == nil { return mdb.Coll(table) } return t.Coll(table) } func initIndex() { many := []mongo.IndexModel{ //batch set indexes //value is the type 1 or -1 { Keys: bson.D{{"userID", 1}, {"type", 1}, {"objID", 1}}, Options: options.Index().SetUnique(true), }, { Keys: bson.D{{"type", 1}}, }, { Keys: bson.D{{"objID", 1}}, }, { Keys: bson.D{{"likedUserID", 1}, {"createdAt", -1}}, }, { Keys: bson.D{{"createdAt", 1}}, }, { Keys: bson.D{{"createdAt", -1}}, }, { 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)) } } // ThumbsUp 点赞 func InsertOne(l *Like) (err error) { l.Uniq = Unique(l.UserID, l.Type, l.ObjID) l.CreatedAt = time.Now() _, err = coll(nil).InsertOne(l) if err != nil { log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "InsertOne", table, "InsertOne", err)) return } return } // InsertMany 批量点赞 func InsertManyBulk(docs []*Like) (insertCount int64, err error) { opts := options.BulkWriteOptions{} opts.SetOrdered(false) models := make([]mongo.WriteModel, 0) for _, v := range docs { models = append(models, mongo.NewInsertOneModel().SetDocument(v)) } res, err := coll(nil).Bulk(models, &opts) if err != nil { log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "InsertManyBulk", table, "Bulk", err)) return } insertCount = res.InsertedCount return } // ThumbsDown 取消点赞 func DeleteOne(uid uint64, lType string, objID primitive.ObjectID) (err error) { _, err = coll(nil).DeleteOne(bson.M{"userID": uid, "type": lType, "objID": objID}) if err != nil { log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "DeleteOne", table, "DeleteOne", err), log.Any("uid", uid), log.Any("lType", lType), log.Any("objID", objID), ) return } return } // ThumbsDownBatch 批量取消点赞 func DeleteMany(uid uint64, lType string, objID []primitive.ObjectID) (err error) { _, err = coll(nil).DeleteMany(bson.M{"userID": uid, "type": lType, "objID": bson.M{"$in": objID}}) if err != nil { log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "DeleteMany", table, "DeleteOne", err), log.Any("uid", uid), log.Any("lType", lType), log.Any("objID", objID), ) return } return } // FindLiked 获取单条点赞记录 验证是否已经点过赞 func FindOneByUIDAndObjID(uid uint64, objID primitive.ObjectID) (data Like, err error) { err = coll(nil).FindOne(&data, bson.M{"userID": uid, "objID": objID}) if err != nil { log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "FindOneByUIDAndObjID", table, "FindOne", err), log.Any("uid", uid), log.Any("objID", objID), ) return } return } // FindLiked 根据对象id获取点赞信息 func FindLikesByObjIDS(lType string, uid uint64, CIDs []primitive.ObjectID) (data []Like, err error) { query := bson.M{"userID": uid, "type": lType, "objID": bson.M{"$in": CIDs}} err = coll(nil).Find(&data, query) if err != nil { log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "FindLikesByObjIDS", table, "Find", err), log.Any("uid", uid), log.Any("lType", lType), log.Any("CIDs", CIDs), ) return } return } // FindLiked 根据对象id获取点赞信息 func FindLikesByTypeAndUID(lType string, uid uint64, pageNumber int, pageSize int) (data []LikeOIDRes, hasNext bool, err error) { query := bson.M{"userID": uid, "type": lType} skip := int64(pageSize * (pageNumber - 1)) limit := int64(pageSize + 1) opts := options.FindOptions{ Skip: &skip, Limit: &limit, Sort: bson.D{{"createdAt", -1}}, Projection: bson.M{"_id": 0, "objID": 1}, } err = coll(nil).Find(&data, query, &opts) if err != nil { log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "FindLikesByTypeAndUID", table, "Find", err), log.Any("uid", uid), log.Any("lType", lType), ) return } if len(data) > pageSize { hasNext = true data = data[:pageSize] } return } // 从给定的uniq列表中获取like状态映射:uniq->Statue // uniq通过uniq()获取 func LikeStatueMap(uniqList []string) (map[string]bool, error) { filter := bson.M{ "uniq": bson.M{"$in": uniqList}, } existLikeList := make([]Like, 0, len(uniqList)) err := coll(nil).Find(&existLikeList, filter) if err != nil { 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 } // LLCount 喜欢总数 func FindLikeIDSByTypeAndUID(lType string, uid uint64) (like []*SimpleRes, err error) { opts := options.Find() opts.SetProjection(bson.M{"objID": 1}) err = coll(nil).Find(&like, bson.M{"userID": uid, "type": lType}, opts) if err != nil { log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "FindLikeIDSByTypeAndUID", table, "Find", err), log.Any("uid", uid), log.Any("lType", lType), ) } return } // IsLikeVideos 是否点赞批量查询 func IsLikeVideos(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 []Like cond := likeVideoStatusFilter(uid, videoIDs) opts := options.Find().SetProjection(bson.M{"_id": 0, "objID": 1}) err := coll(nil).Find(&infos, cond, opts) if err != nil { log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "IsLikeVideos", 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 likeVideoStatusFilter(uid uint64, videoIDs []primitive.ObjectID) bson.M { return bson.M{ "userID": uid, "type": bson.M{"$in": []string{ constant.LikeTypeSP, constant.LikeTypeShort, constant.LikeTypeCover, constant.LikeTypePic, constant.LikeTypeSEED_LINK, constant.LikeTypeAiPlaza, }}, "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 } func ListByLikedUserID(uid uint64, skip, limit int64) ([]Like, error) { likedUserID := LikedUserIDMatch{&uid} sort := bson.D{{"createdAt", -1}} return List(sort, skip, limit, likedUserID.New()) } func GetImageLikeList(uid uint64, skip, limit int64) (out []*Like, err error) { filter := bson.M{"userID": uid, "type": "image"} if err = coll(nil).Find(&out, filter, options.Find().SetSkip(skip).SetLimit(limit).SetSort(bson.M{"createdAt": -1})); err != nil { log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "GetImageLikeList", table, "Find", err), log.Any("uid", uid), log.Any("skip", skip), log.Any("limit", limit), ) return nil, err } return } // IsLikeByType 是否点赞批量查询 func IsLikeByType(uid uint64, typ []string, IDS []primitive.ObjectID) (map[primitive.ObjectID]bool, error) { m := make(map[primitive.ObjectID]bool) var infos []Like cond := bson.M{"userID": uid, "type": bson.M{"$in": typ}, "objID": bson.M{"$in": IDS}} err := coll(nil).Find(&infos, cond) if err != nil { log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "IsLikeByType", table, "Find", err), log.Any("uid", uid), log.Any("IDS", IDS), ) return m, err } for _, i := range infos { m[i.ObjID] = true } return m, nil }