package kwrankmod import ( "fmt" "math/rand" "time" "91porn-server/common" "91porn-server/common/db" "91porn-server/common/log" "91porn-server/common/timeutil/timerange" "91porn-server/models" "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.KWRankStat func coll(t *db.MongoTool) *db.MongoTool { if t == nil { return mdb.Coll(table) } return t.Coll(table) } // InitIndex 设置index func initIndex() { many := []mongo.IndexModel{ { Keys: bson.D{{Key: "word", Value: 1}}, }, { Keys: bson.D{{Key: "sumDate", Value: -1}}, }, { Keys: bson.D{{Key: "sumDate", Value: -1}, {Key: "word", Value: 1}}, Options: options.Index().SetUnique(true), }, { Keys: bson.D{{Key: "count", Value: -1}}, }, { Keys: bson.D{{Key: "sortKey", Value: -1}}, //大的排前面 }, { Keys: bson.D{{Key: "sumDate", Value: -1}, {Key: "sortKey", Value: -1}, {Key: "count", Value: -1}}, //大的排前面 }, { Keys: bson.D{{Key: "recordAt", Value: -1}}, }, } if _, err := coll(nil).CreateIndex(many); err != nil { panic(fmt.Sprintf("%s model set index err ==>[%+v]", table, err)) } } func Insert(kw Word) error { now := time.Now() kw.CreatedAt = now kw.UpdatedAt = now if _, err := coll(nil).InsertOne(kw); err != nil { log.ZapLog.Error(fmt.Sprintf("coll:%s Insert fail error:%+v:", table, err)) return err } return nil } func Update(id ObjectID, doc RankDoc) error { update, err := common.ToBsonM(doc) if err != nil { return fmt.Errorf("coll:%s update ToBsonM fail, error:%+v ", table, err) } update["updatedAt"] = time.Now() if _, err := coll(nil).UpdateOne(M{"_id": id}, M{"$set": update}); err != nil { log.ZapLog.Error(fmt.Sprintf("coll:%s update fail error:%+v:", table, err)) return err } return nil } // DeleteOne DeleteOne func Delete(id ObjectID) error { _, err := coll(nil).DeleteOne(M{"_id": id}) if err != nil { log.ZapLog.Error(fmt.Sprintf("coll:%s DeleteOne fail error:%+v:", table, err)) return err } return nil } var rankSort = bson.D{ {Key: "sumDate", Value: -1}, {Key: "sortKey", Value: -1}, {Key: "count", Value: -1}, } var enableIsTrue = true // RecentRanking RecentRanking func RecentRanking(limit int64) ([]Keyword, error) { kws, err := KwsList(rankSort, 0, limit, (&EnableMatch{&enableIsTrue}).New()) if err != nil { log.ZapLog.Error(fmt.Sprintf("coll:%s RecentRanking fail error:%+v:", table, err)) } return kws, err } func ChangeStatTrans(trans *db.MongoTool, position time.Time, recordTime time.Time, setList []RankSetDoc) error { if len(setList) == 0 { return nil } sumDate := timerange.LocDayRange(position).Head // create the slice of write models writes := make([]mongo.WriteModel, len(setList)) for i, doc := range setList { filter := M{ "sumDate": sumDate, "word": doc.Word, } update := M{ "$setOnInsert": M{ "sumDate": sumDate, "word": doc.Word, "enable": true, //首次插入时使能 "createdAt": time.Now(), }, "$set": M{ "count": doc.Count, //设计为统计表keywordStat聚合word得到 "sortKey": doc.Count, //控制app端排序 "recordAt": recordTime, "updatedAt": time.Now(), }, } writes[i] = mongo.NewUpdateOneModel(). SetFilter(filter). SetUpdate(update). SetUpsert(true) log.Debug(fmt.Sprintf("sumDate:%s table:%s [ word:%+v filter:%+v update:%+v ]\n", sumDate, table, doc.Word, filter, update)) } //bulkWrite 不是原子操作 不具备事务性 opt := (&options.BulkWriteOptions{}).SetOrdered(false) //设为无序,触发并行写,提升写效率 _, err := coll(trans).Bulk(writes, opt) return err } func GetListNewest(limit int64) (WordArray, error) { sort := bson.D{{Key: "createdAt", Value: -1}} enable := true enableMatch := EnableMatch{&enable} return List(sort, 0, limit, enableMatch.New()) } func GetListRandom(limit int64) (WordArray, error) { enable := true enableMatch := EnableMatch{&enable} count, err := Count(enableMatch.New()) if err != nil { return nil, err } maxSkip := count - limit if maxSkip < 0 { maxSkip = 0 } randSkip := rand.Int63n(maxSkip) sort := bson.D{{Key: "count", Value: -1}} return List(sort, randSkip, limit) } func DeleteBeforeSumDate(t *db.MongoTool, tm time.Time) error { _, err := coll(t).DeleteMany(bson.M{"sumDate": bson.M{"$lt": tm}}) return err }