From 1b5ef757b7852d5454f4eb1cb8f0b1a0bf9f8f4c Mon Sep 17 00:00:00 2001 From: Havoc412 <2993167370@qq.com> Date: Fri, 8 Nov 2024 16:57:47 +0800 Subject: [PATCH] fit redisgo to lrange --- app/http/controller/web/animal_controller.go | 17 ++++---- app/http/validator/web/animal/list.go | 2 +- app/model/encounter.go | 7 ++++ app/utils/redis_factory/client.go | 43 ++++++++++++++++++++ config/config.yml | 3 +- test/redis_test.go | 43 ++++++++++++++++++-- 6 files changed, 102 insertions(+), 13 deletions(-) diff --git a/app/http/controller/web/animal_controller.go b/app/http/controller/web/animal_controller.go index 468bb12..9b39afd 100644 --- a/app/http/controller/web/animal_controller.go +++ b/app/http/controller/web/animal_controller.go @@ -46,7 +46,7 @@ func (a *Animals) List(context *gin.Context) { mode := context.GetString(consts.ValidatorPrefix + "mode") var preferCatsId []int64 - var redis_num int + var redis_preferCatsId []int64 var key int64 if mode == consts.AnimalPreferMode { key = int64(context.GetFloat64(consts.ValidatorPrefix + "key")) @@ -54,17 +54,17 @@ func (a *Animals) List(context *gin.Context) { redisClient := redis_factory.GetOneRedisClient() defer redisClient.ReleaseOneRedisClient() if key != 0 { - redis_num, _ = redisClient.Int(redisClient.Execute("get", key)) + redis_preferCatsId, _ = redisClient.Int64sFromList(redisClient.Execute("lrange", key, 0, -1)) } else { key = variable.SnowFlake.GetId() } - if redis_num == skip { + if len(redis_preferCatsId) == skip { preferCatsId, _ = getPreferCatsId(int(userId), int(num)) - redis_num += len(preferCatsId) - } + redis_preferCatsId = append(redis_preferCatsId, preferCatsId...) - if _, err := redisClient.String(redisClient.Execute("set", key, redis_num)); err != nil { + if _, err := redisClient.String(redisClient.Execute("lpush", key, redis_preferCatsId)); err != nil { + } } } @@ -91,9 +91,9 @@ func (a *Animals) List(context *gin.Context) { // 计算还需要多少动物 num -= len(animalsWithLike) - skip -= redis_num + skip = max(0, skip-len(redis_preferCatsId)) if num > 0 { - additionalAnimals := curd.CreateAnimalsCurdFactory().List(attrs, gender, breed, sterilization, status, department, preferCatsId, num, skip, int(userId)) + additionalAnimals := curd.CreateAnimalsCurdFactory().List(attrs, gender, breed, sterilization, status, department, redis_preferCatsId, num, skip, int(userId)) // 将 additionalAnimals 整合到 animalsWithLike 的后面 animalsWithLike = append(animalsWithLike, additionalAnimals...) } @@ -155,6 +155,7 @@ func (a *Animals) Detail(context *gin.Context) { response.Fail(context, errcode.AnimalNoFind, errcode.ErrMsg[errcode.AnimalNoFind], "") } } + func (a *Animals) Create(context *gin.Context) { userId := strconv.Itoa(int(context.GetFloat64(consts.ValidatorPrefix + "user_id"))) // STAGE-1 Get Params diff --git a/app/http/validator/web/animal/list.go b/app/http/validator/web/animal/list.go index 936682e..bcd034a 100644 --- a/app/http/validator/web/animal/list.go +++ b/app/http/validator/web/animal/list.go @@ -21,7 +21,7 @@ type List struct { UserId int `form:"user_id" json:"user_id"` Mode string `form:"mode" json:"mode"` // INFO 控制 animal_ctl 的查询模式。 // default: 简单调用 List 函数 || prefer: 优先返回和用户关联度更高的目标。 - Ket string `form:"key" json:"key"` // redis の key 值。 + Key int64 `form:"key" json:"key"` // redis の key 值。 } func (l List) CheckParams(context *gin.Context) { diff --git a/app/model/encounter.go b/app/model/encounter.go index c6047cc..9e4303d 100644 --- a/app/model/encounter.go +++ b/app/model/encounter.go @@ -169,11 +169,18 @@ func (e *Encounter) ShowByID(id int64) (temp *Encounter, err error) { // return } +/** + * @description: 过去 1 个月,发送过路遇表的 ids,同时去重。 + * @param {*} user_id + * @param {int} num + * @return {*} + */ func (e *Encounter) EncounteredCats(user_id, num int) ([]int64, error) { sql := `SELECT eal.animal_id FROM encounter_animal_links eal JOIN encounters e ON e.id = eal.encounter_id AND e.user_id = ? + WHERE e.updated_at >= DATE_SUB(CURDATE(), INTERVAL 1 MONTH) ORDER BY e.updated_at DESC LIMIT ?` diff --git a/app/utils/redis_factory/client.go b/app/utils/redis_factory/client.go index 048c27b..d66402e 100644 --- a/app/utils/redis_factory/client.go +++ b/app/utils/redis_factory/client.go @@ -6,6 +6,9 @@ import ( "catface/app/global/variable" "catface/app/utils/yml_config" "catface/app/utils/yml_config/ymlconfig_interf" + "fmt" + "strconv" + "strings" "time" "github.com/gomodule/redigo/redis" @@ -161,3 +164,43 @@ func (r *RedisClient) Bytes(reply interface{}, err error) ([]byte, error) { } // 以上封装了很多最常见类型转换函数,其他您可以参考以上格式自行封装 + +// 配合 List 类型使用; 配合 lpush 来获取返回的信息。 // UPDATE 感觉 前后的 [] 机制,应该是 go 导致的,em,肯定能优化, +func (r *RedisClient) Int64sFromList(reply interface{}, err error) ([]int64, error) { + values, err := redis.Values(reply, err) + if err != nil { + return nil, err + } + // fmt.Println("len", len(values)) + + if len(values) == 0 { + return nil, fmt.Errorf("empty values") + } + + // 假设 values 只有一个元素,且该元素是一个字符串 // INFO 这里返回的是一个 []uint8 的类型,但是处理的时候 string化 就会 导致前后的 '[]' + strValue := string(values[0].([]byte)) + // fmt.Println("Original string:", strValue) + + // 去掉前后的括号 + strValue = strings.TrimPrefix(strValue, "[") + strValue = strings.TrimSuffix(strValue, "]") + // fmt.Println("Trimmed string:", strValue) + + // 拆分成单独的数字字符串 + strValues := strings.Split(strValue, " ") + // fmt.Println("Split values:", strValues) + + var result []int64 + for _, str := range strValues { + // 将字符串转换为 int64 + intValue, err := strconv.ParseInt(str, 10, 64) + if err != nil { + return nil, err + } + + // 将转换后的 int64 值添加到结果切片中 + result = append(result, intValue) + } + + return result, nil +} diff --git a/config/config.yml b/config/config.yml index 4539f2a..dbfb499 100644 --- a/config/config.yml +++ b/config/config.yml @@ -22,7 +22,8 @@ Token: IsCacheToRedis: 0 #用户token是否缓存到redis, 如果已经正确配置了redis,建议设置为1, 开启redis缓存token,(1=用户token缓存到redis; 0=token只存在于mysql) Redis: - Host: "113.44.68.213" # 服务器本地调用。 开发时也在本地启动一个。 + # Host: "113.44.68.213" # 服务器本地调用。 开发时也在本地启动一个。 + Host: "127.0.0.1" Port: 6379 Auth: "" MaxIdle: 10 diff --git a/test/redis_test.go b/test/redis_test.go index 4a930fa..83e3942 100644 --- a/test/redis_test.go +++ b/test/redis_test.go @@ -38,18 +38,36 @@ func TestRedisKeyInt64(t *testing.T) { id := variable.SnowFlake.GetId() - res, err := redisClient.String(redisClient.Execute("set", id, 1)) + _, err := redisClient.String(redisClient.Execute("set", id, 10)) if err != nil { t.Errorf("单元测试失败,%s\n", err.Error()) } - if res, err = redisClient.String(redisClient.Execute("get", id)); err != nil { + if res, err := redisClient.Int(redisClient.Execute("get", id)); err != nil { t.Errorf("单元测试失败,%s\n", err.Error()) } else { - t.Logf("单元测试通过,%s\n", res) + t.Logf("单元测试通过,%d\n", res) } } +// func TestRedisKeyInt64s(t *testing.T) { +// redisClient := redis_factory.GetOneRedisClient() +// defer redisClient.ReleaseOneRedisClient() + +// key := variable.SnowFlake.GetId() + +// _, err := redisClient.String(redisClient.Execute("set", key, []int64{1, 2, 3})) +// if err != nil { +// t.Errorf("单元测试失败,%s\n", err.Error()) +// } + +// if res, err := redisClient.Int64s(redisClient.Execute("get", key)); err != nil { +// t.Errorf("单元测试失败,%s\n", err.Error()) +// } else { +// t.Logf("单元测试通过,%v\n", res) +// } +// } + // hash 键、值 func TestRedisHashKey(t *testing.T) { @@ -133,3 +151,22 @@ func TestRedisMulti(t *testing.T) { } // 其他请参照以上示例即可 + +// 测试 redis 的列表属性 +func TestRedisList(t *testing.T) { + redisClient := redis_factory.GetOneRedisClient() + defer redisClient.ReleaseOneRedisClient() + + key := variable.SnowFlake.GetId() + list := []int64{1, 2, 6} + _, err := redisClient.Int64(redisClient.Execute("lpush", key, list)) + if err != nil { + t.Errorf("单元测试失败,%s\n", err.Error()) + } + + if res, err := redisClient.Int64sFromList(redisClient.Execute("lrange", key, 0, -1)); err != nil { + t.Errorf("单元测试失败,%s\n", err.Error()) + } else { + t.Logf("单元测试通过,%v\n", res) + } +}