package audiobookmod import ( "encoding/json" "errors" "fmt" "math/rand" "time" "91porn-server/app/appg" "91porn-server/app/service/searcher" "91porn-server/common" "91porn-server/common/constant/redisconst" "91porn-server/common/db" "91porn-server/common/log" "91porn-server/models" "91porn-server/models/commod" "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" ) const table = models.AudioBook // InitIndex 设置index func initIndex() { coll := coll(nil) many := []mongo.IndexModel{ { Keys: bson.D{{Key: "number", Value: 1}}, Options: options.Index().SetUnique(true), }, { Keys: bson.D{{Key: "isActive", Value: 1}}, }, { Keys: bson.D{{Key: "fType", Value: 1}}, }, { Keys: bson.D{{Key: "anchor", Value: 1}}, }, } if _, err := coll.CreateIndex(many); err != nil { panic(fmt.Sprintf("%s model set index err ==>[%+v]", table, err)) } } func coll(t *db.MongoTool) *db.MongoTool { if t == nil { return mdb.Coll(table) } return t.Coll(table) } func GetByID(id primitive.ObjectID) (ab AudioBookAppRes, err error) { redisKey := redisconst.DataCachKey(table, id.Hex()) redisc := appg.Redis if redisc == nil || !redisc.Exists(redisKey) { if err = coll(nil).FindOne(&ab, bson.M{"_id": id}); err != nil { log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "GetByID", table, "FindOne", err), log.Any("id", id.Hex())) return } if redisc == nil { return } var jsonBytes []byte jsonBytes, err = json.Marshal(&ab) if err != nil { return } err = redisc.Set(redisKey, string(jsonBytes), redisconst.DataCachExpire) return } str, err := redisc.Get(redisKey) if err != nil { return } if str == nil { err = errors.New("redis key is null") return } if err = json.Unmarshal([]byte(*str), &ab); err != nil { log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "GetByID", table, "FindOne", err), log.Any("id", id.Hex())) return } return } // todo app func GetByIds(ids []primitive.ObjectID) (res []AudioBookAppRes, err error) { data := make([]AudioBookAppRes, 0) f := bson.M{} if ids != nil { f["_id"] = bson.M{"$in": ids} } if err = coll(nil).Find(&data, f); err != nil { log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "GetByBusinessDateAndCityInIds", table, "Find", err), log.Any("cond", f)) return } tempM := make(map[primitive.ObjectID]AudioBookAppRes) for i := range data { tempM[data[i].ID] = data[i] } res = make([]AudioBookAppRes, len(ids)) for i := range ids { res[i] = tempM[ids[i]] } return } func GetByFType(fType string, page commod.Page) (data []AudioBookBase, hasNext bool, err error) { data = make([]AudioBookBase, 0) skip := int64(page.Skip()) limit := int64(page.Limit() + 1) sortWord := "createdAt" opts := options.FindOptions{ Skip: &skip, Limit: &limit, Sort: bson.D{{Key: sortWord, Value: -1}}, } f := bson.M{"isActive": true} if fType != "" { if fType == ListenPermissionBuyZone { f["contentSet.listenPermission"] = ListenPermissionBuy } else { f["fType"] = fType } } if err = coll(nil).Find(&data, f, &opts); err != nil { log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "GetByFType", table, "Find", err), log.Any("cond", f)) return } if uint64(len(data)) > page.PageSize { hasNext = true data = data[:page.PageSize] } for i := range data { for j := range data[i].ContentSet { data[i].ContentSet[j].ListenPermission = 3 data[i].ContentSet[j].Price = 0 } } return } func GetByAnchor(anchor string, page commod.Page) (data []AudioBookBase, hasNext bool, err error) { data = make([]AudioBookBase, 0) skip := int64(page.Skip()) limit := int64(page.Limit() + 1) sortWord := "createdAt" opts := options.FindOptions{ Skip: &skip, Limit: &limit, Sort: bson.D{{Key: sortWord, Value: -1}}, } f := bson.M{"isActive": true} if anchor != "" { f["anchor"] = anchor } if err = coll(nil).Find(&data, f, &opts); err != nil { log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "GetByFType", table, "Find", err), log.Any("cond", f)) return } if uint64(len(data)) > page.PageSize { hasNext = true data = data[:page.PageSize] } return } // 获取热门 func GetHots(page commod.Page) (data []AudioBookBase, hasNext bool, err error) { data = make([]AudioBookBase, 0) skip := int64(page.Skip()) limit := int64(page.Limit() + 1) sortWord := "countPurchases" opts := options.FindOptions{ Skip: &skip, Limit: &limit, Sort: bson.D{{Key: sortWord, Value: -1}}, } f := bson.M{"isActive": true} if err = coll(nil).Find(&data, f, &opts); err != nil { log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "GetByFType", table, "Find", err), log.Any("cond", f)) return } if uint64(len(data)) > page.PageSize { hasNext = true data = data[:page.PageSize] } return } func GetRandomPush(size int) (data []AudioBookBase, err error) { data = make([]AudioBookBase, 0) redisK := "tempSet:" + RedisSetKey + ":randomData" redisc := appg.Redis if redisc == nil || !redisc.Exists(redisK) { f := bson.M{"isActive": true} var total int64 total, err = randomCount(f) if err != nil { return } var limit int64 = 100 var skip int64 = 0 if total-limit > limit { skip = rand.Int63n(total - limit) } opts := options.FindOptions{ Skip: &skip, Limit: &limit, } if err = coll(nil).Find(&data, f, &opts); err != nil { log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "GetRandomPush", table, "Find", err), log.Any("filter", f)) return } if len(data) < 1 { return } if redisc == nil { return } tempd := make([]string, len(data)) for i := range data { var strB []byte strB, err = json.Marshal(data[i]) if err != nil { return } tempd[i] = string(strB) } if _, err = redisc.SAdd(redisK, tempd); err != nil { return } _, _ = redisc.ExpireKey(redisK, time.Minute*10) } tempd, err := redisc.SRandMemberN(redisK, int64(size)) if len(tempd) < 1 { return data, errors.New("redis key is null") } data = make([]AudioBookBase, len(tempd)) for i := range data { _ = json.Unmarshal([]byte(tempd[i]), &data[i]) } return } func GetRandomPush_PermissionBuy(size int) (data []AudioBookBase, err error) { data = make([]AudioBookBase, 0) redisK := "tempSet:" + RedisSetKey + ":randomData:permissionBuy" redisc := appg.Redis if redisc == nil || !redisc.Exists(redisK) { f := bson.M{"isActive": true, "contentSet.listenPermission": ListenPermissionBuy} var total int64 total, err = randomCount(f) if err != nil { return } var limit int64 = 100 var skip int64 = 0 if total-limit > limit { skip = rand.Int63n(total - limit) } opts := options.FindOptions{ Skip: &skip, Limit: &limit, } if err = coll(nil).Find(&data, f, &opts); err != nil { log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "GetRandomPush_PermissionBuy", table, "Find", err), log.Any("filter", f)) return } if len(data) < 1 { return } if redisc == nil { return } tempd := make([]string, len(data)) for i := range data { var strB []byte strB, err = json.Marshal(data[i]) if err != nil { return } tempd[i] = string(strB) } if _, err = redisc.SAdd(redisK, tempd); err != nil { return } _, _ = redisc.ExpireKey(redisK, time.Minute*10) } tempd, err := redisc.SRandMemberN(redisK, int64(size)) if len(tempd) < 1 { return data, errors.New("redis key is null") } data = make([]AudioBookBase, len(tempd)) for i := range data { _ = json.Unmarshal([]byte(tempd[i]), &data[i]) } return } func GetRandomPush_PermissionVIP(size int) (data []AudioBookBase, err error) { data = make([]AudioBookBase, 0) redisK := "tempSet:" + RedisSetKey + ":randomData:PermissionVIP" redisc := appg.Redis if redisc == nil || !redisc.Exists(redisK) { f := bson.M{"isActive": true, "contentSet.listenPermission": ListenPermissionVIP} var total int64 total, err = randomCount(f) if err != nil { return } var limit int64 = 100 var skip int64 = 0 if total-limit > limit { skip = rand.Int63n(total - limit) } opts := options.FindOptions{ Skip: &skip, Limit: &limit, } if err = coll(nil).Find(&data, f, &opts); err != nil { log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "GetRandomPush_PermissionVIP", table, "Find", err), log.Any("filter", f)) return } if len(data) < 1 { return } if redisc == nil { return } tempd := make([]string, len(data)) for i := range data { var strB []byte strB, err = json.Marshal(data[i]) if err != nil { return } tempd[i] = string(strB) } if _, err = redisc.SAdd(redisK, tempd); err != nil { return } _, _ = redisc.ExpireKey(redisK, time.Minute*10) } tempd, err := redisc.SRandMemberN(redisK, int64(size)) if len(tempd) < 1 { return data, errors.New("redis key is null") } data = make([]AudioBookBase, len(tempd)) for i := range data { _ = json.Unmarshal([]byte(tempd[i]), &data[i]) } return } func GetFTypes() (data []interface{}, err error) { data = make([]interface{}, 0) redisKey := RedisSetKey + ":fType" redisc := appg.Redis if redisc == nil || !redisc.Exists(redisKey) { data, err = coll(nil).Distinct("fType", bson.M{}) if err != nil { log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "GetCitys", table, "Distinct", err)) return nil, err } if redisc == nil { return data, err } jsonBytes, err := json.Marshal(data) if err != nil { return data, err } _ = redisc.Set(redisKey, string(jsonBytes), time.Minute*10) return data, err } str, err := redisc.Get(redisKey) if err != nil { log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "GetFTypes", table, "Find", err)) return nil, err } if str == nil { return data, errors.New("redis key is null") } err = json.Unmarshal([]byte(*str), &data) return } func SearchTitle(title string, page commod.Page) (data []AudioBookBase, hasNext bool, err error) { data = make([]AudioBookBase, 0) skip := int64(page.Skip()) limit := int64(page.Limit() + 1) opts := options.FindOptions{ Skip: &skip, Limit: &limit, Sort: bson.D{{Key: "createdAt", Value: 1}}, } f := bson.M{"isActive": true} f["$or"] = bson.A{ bson.M{"title": primitive.Regex{ Pattern: title, Options: "", }}, } if err = coll(nil).Find(&data, f, &opts); err != nil { log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "SearchTitle", table, "Find", err), log.Any("cond", f)) return } if uint64(len(data)) > page.PageSize { hasNext = true data = data[:page.PageSize] } return } func IncCount(id primitive.ObjectID, inc CountInc) (err error) { res, err := coll(nil).UpdateOne(bson.M{"_id": id}, bson.M{"$inc": inc}) if err != nil { log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "IncCount", table, "UpdateOne", err), log.Any("id", id), log.Any("inc", inc)) return } if res.ModifiedCount <= 0 { if err != nil { log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "IncCount", table, "UpdateOne", err), log.Any("id", id), log.Any("inc", inc), log.Any("res", res)) return } } return } func GetNew(opt searcher.Opter) (data []AudioBookAppRes, hasNext bool, err error) { data = make([]AudioBookAppRes, 0) skip := opt.Skip() limit := opt.Limit() + 1 opts := options.FindOptions{ Skip: &skip, Limit: &limit, Sort: bson.D{{Key: "createdAt", Value: -1}}, } f := bson.M{"isActive": true} if err = coll(nil).Find(&data, f, &opts); err != nil { log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "GetNew", table, "Find", err), log.Any("cond", f)) return } if int64(len(data)) > opt.Limit() { hasNext = true data = data[:opt.Limit()] } return } func randomCount(f bson.M) (count int64, err error) { count, err = coll(nil).Count(f) if err != nil { log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "GetCitys", table, "Distinct", err)) return } return } // todo web // StdFind 通用查询 func StdFind(q QuerySelector, page commod.Page) (data []AudioBook, total int64, err error) { data = make([]AudioBook, 0) skip := int64(page.Skip()) limit := int64(page.Limit()) opts := options.FindOptions{ Skip: &skip, Limit: &limit, } f, err := common.ToBsonM(q) if err != nil { log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "StdFind", table, "ToBsonM", err), log.Any("cond", f)) return } if q.Title != nil { f["title"] = primitive.Regex{ Pattern: *q.Title, Options: "", } } if err = coll(nil).Find(&data, f, &opts); err != nil { log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "StdFind", table, "Find", err), log.Any("cond", f)) return } total, err = coll(nil).Count(f) if err != nil { log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "StdFind", table, "Count", err), log.Any("cond", f)) } return } // IsExisted 查询 func IsExisted(id primitive.ObjectID) (ok bool, err error) { ok, err = coll(nil).Exists(bson.M{"_id": id}) if err != nil { log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "IsExisted", table, "Exists", err), log.Any("id", id)) return } return } // InsertAudioBook 插入一条数据 func InsertAudioBook(p *AudioBook) (err error) { p.CreatedAt = time.Now() if _, err = coll(nil).InsertOne(p); err != nil { log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "InsertAudioBook", table, "InsertOne", err)) } return } // InsertBulket 插入一条数据 func InsertBulket(p []AudioBookUpsertEdit) (err error) { fmt.Println("------------", len(p)) now := time.Now() wm := make([]mongo.WriteModel, len(p)) for k := range p { filter := bson.M{"number": p[k].Number} update := bson.M{"$set": p[k], "$setOnInsert": bson.M{"createdAt": now, "contentSet": p[k].ContentSet}} model := mongo.NewUpdateOneModel(). SetFilter(filter). SetUpdate(update). SetUpsert(true) wm[k] = model } ordered := false opts := options.BulkWriteOptions{ Ordered: &ordered, } if _, err = coll(nil).Bulk(wm, &opts); err != nil { log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "InsertMany", table, "InsertMany", err)) } return } // InsertAudioBook 插入一条数据 func InsertMany(p []AudioBook) (err error) { if _, err = coll(nil).InsertMany(p); err != nil { log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "InsertMany", table, "InsertMany", err)) } return } // UpdateAudioBook 修改AudioBook类型 func UpdateAudioBookBatch(sets []EditSelector) (err error) { now := time.Now() wm := make([]mongo.WriteModel, len(sets)) for k := range sets { sets[k].UpdatedAt = now filter := bson.M{"_id": sets[k].ID} update := bson.M{"$set": sets[k]} model := mongo.NewUpdateOneModel(). SetFilter(filter). SetUpdate(update). SetUpsert(false) wm[k] = model } ordered := false opts := options.BulkWriteOptions{ Ordered: &ordered, } if _, err = coll(nil).Bulk(wm, &opts); err != nil { log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "InsertMany", table, "InsertMany", err)) } return } // UpdateAudioBook 修改AudioBook类型 func UpdateAudioBook(set EditSelector) error { set.UpdatedAt = time.Now() setM, err := common.ToBsonM(set) if err != nil { log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "ToBsonM", table, "UpdateOne", err), log.Any("set", set)) return err } if _, err = coll(nil).UpdateOne(bson.M{"_id": set.ID}, bson.M{"$set": setM}); err != nil { log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "UpdateAudioBook", table, "UpdateOne", err), log.Any("set", set), ) return err } return nil } // RemoveAudioBook 删除AudioBook类型 func RemoveAudioBook(id string) error { OID, err := primitive.ObjectIDFromHex(id) if err != nil { log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "RemoveAudioBook", table, "ObjectIDFromHex", err), log.Any("id", id), ) return err } if _, err = coll(nil).DeleteOne(bson.M{"_id": OID}); err != nil { log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "RemoveAudioBook", table, "DeleteOne", err), log.Any("OID", OID), ) return err } return nil } // todo skd // 获取ES同步数据 func GetListByUpdateTimeRange(start time.Time, end time.Time) (data []AudioBookBase, err error) { var query = bson.M{ "updatedAt": bson.M{"$gte": start, "$lt": end}, } if err = coll(nil).Find(&data, query); err != nil { log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "GetListByUpdateTimeRange", table, "Find", err), log.Any("start", start), log.Any("end", end), ) return } return } func GetListByCond(cond bson.M, opts *options.FindOptions) ([]AudioBook, error) { var data []AudioBook if err := coll(nil).Find(&data, cond, opts); err != nil { return nil, err } return data, nil }