refactor(web): 重构动物列表查询逻辑

- 优化了 prefer 模式下的查询流程,减少了冗余代码
- 重构了 getPreferCatsId 函数,增加了 skip 参数支持分页查询
- 修改了 Encounter 模型中的 EncounteredCats 方法,支持 DISTINCT 查询和分页
- 提高了查询效率,减少了数据库访问次数
This commit is contained in:
Havoc412 2024-11-18 13:06:51 +08:00
parent e33f9a1801
commit 4d2f304ab7
2 changed files with 40 additions and 72 deletions

View File

@ -36,9 +36,10 @@ func (a *Animals) List(context *gin.Context) {
mode := context.GetString(consts.ValidatorPrefix + "mode")
var preferCatsId []int64
// TAG prefer MODE 查询模式。
var redis_preferCatsId []int64
var key int64
var animalsWithLike []model.AnimalWithLikeList
if mode == consts.AnimalPreferMode {
key = int64(context.GetFloat64(consts.ValidatorPrefix + "key"))
@ -51,35 +52,17 @@ func (a *Animals) List(context *gin.Context) {
}
if len(redis_preferCatsId) == skip {
preferCatsId, _ = getPreferCatsId(int(userId), int(num))
redis_preferCatsId = append(redis_preferCatsId, preferCatsId...)
preferCatsId, preferCats, _ := getPreferCatsId(int(userId), num, skip, attrs)
if len(preferCatsId) > 0 {
redis_preferCatsId = append(redis_preferCatsId, preferCatsId...)
animalsWithLike = append(animalsWithLike, preferCats...)
}
if _, err := redisClient.String(redisClient.Execute("lpush", key, redis_preferCatsId)); err != nil {
}
}
}
var animalsWithLike []model.AnimalWithLikeList
if len(preferCatsId) > 0 {
// 创建一个 map 来存储查询结果
animalMap := make(map[int64]model.Animal, len(preferCatsId))
attrsSlice := query_handler.StringToStringArray(attrs)
attrsSlice = append(attrsSlice, "id")
animals := model.CreateAnimalFactory("").ShowByIDs(preferCatsId, attrsSlice...)
for _, v := range animals {
animalMap[v.Id] = v
}
// 根据 preferCatsId 的顺序构建最终结果列表
for _, id := range preferCatsId {
if animal, ok := animalMap[id]; ok {
animalsWithLike = append(animalsWithLike, model.AnimalWithLikeList{Animal: animal})
}
}
}
// 计算还需要多少动物
num -= len(animalsWithLike)
skip = max(0, skip-len(redis_preferCatsId))
@ -100,25 +83,30 @@ func (a *Animals) List(context *gin.Context) {
}
// UPDATE 就先简单一些,主要就依靠 encounter - animal_id 来获取一个目标。
func getPreferCatsId(userId, num int) ([]int64, error) {
// STAGE check 一下 key 是否存在。
// if key != "" {
// redisClient := redis_factory.GetOneRedisClient()
// defer redisClient.ReleaseOneRedisClient()
// if res, err := redisClient.Bool(redisClient.Execute("get", key)); err != nil {
// if res { // 如果 redis 返回的是 1则代表 prefer 已经耗尽了。
// return nil, err
// }
// }
// }
// STAGE - 1 模块一,无视条件,获取路遇过的 id 列表;先获取 ID然后再去查询细节信息。
encounteredCats, err := model.CreateEncounterFactory("").EncounteredCats(userId, num)
func getPreferCatsId(userId, num, skip int, attrs string) (ids []int64, list []model.AnimalWithLikeList, err error) {
// STAGE - 1 模块一,无视过滤条件,获取路遇“过”的 id 列表;先获取 ID然后再去查询细节信息。
ids, err = model.CreateEncounterFactory("").EncounteredCats(userId, num, skip)
if err != nil {
// variable.ZapLog.Error("获取用户浏览记录失败", Zap.Error(err))
return encounteredCats, err
if err == nil && len(ids) > 0 {
attrsSlice := query_handler.StringToStringArray(attrs)
attrsSlice = append(attrsSlice, "id")
animalMap := make(map[int64]model.Animal, len(ids))
animals := model.CreateAnimalFactory("").ShowByIDs(ids, attrsSlice...)
for _, v := range animals {
animalMap[v.Id] = v
}
// 根据 preferCatsId 的顺序重构最终结果列表
for _, id := range ids {
if animal, ok := animalMap[id]; ok {
list = append(list, model.AnimalWithLikeList{Animal: animal})
}
}
}
return encounteredCats, nil
return
}
// v0.1

View File

@ -157,21 +157,6 @@ func (e *Encounter) ShowByID(id int64) (temp *Encounter, err error) {
return
}
return
// // 2. search user data
// user := UsersModel{BaseModel: BaseModel{Id: encounter.UsersModelId}}
// if err := user.Select("user_name", "user_avatar").First(&user).Error; err != nil {
// return
// }
// // 3. search animals data
// animals_id := query_handler.StringToint64Array(encounter.AnimalsId)
// var animals []Animal
// if err := e.Model(&animals).Select("id", "avatar", "name").Where("id in (?)", animals_id).Find(&animals).Error; err != nil {
// return
// }
// // TODO 4. 然后整合
// return
}
func (e *Encounter) ShowByIDs(ids []int64, attrs ...string) (temp []Encounter) {
@ -189,30 +174,28 @@ func (e *Encounter) ShowByIDs(ids []int64, attrs ...string) (temp []Encounter) {
}
/**
* @description: 过去 1 个月发送过路遇表的 ids同时去重
* @description: 过去 1 个月发送过路遇表的 ids同时 SQL 去重
* @param {*} user_id
* @param {int} num
* @param {int} num 限制查询的数量
* @return {*}
*/
func (e *Encounter) EncounteredCats(user_id, num int) ([]int64, error) {
sql := `SELECT eal.animal_id
func (e *Encounter) EncounteredCats(user_id, num, skip int) ([]int64, error) {
sql := `SELECT DISTINCT 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 ?`
WHERE e.updated_at >= DATE_SUB(CURDATE(), INTERVAL 1 MONTH)
ORDER BY e.updated_at DESC
LIMIT ? OFFSET ?`
rows, err := e.Raw(sql, user_id, num).Rows()
rows, err := e.Raw(sql, user_id, num, skip).Rows()
if err != nil {
log.Println("查询失败:", err)
return nil, err
}
defer rows.Close()
// Scan 同时去重。
var temp []int64
seen := make(map[int64]bool)
var animal_ids []int64
for rows.Next() {
var animal_id int64
@ -220,10 +203,7 @@ func (e *Encounter) EncounteredCats(user_id, num int) ([]int64, error) {
log.Println("扫描失败:", err)
return nil, err
}
if !seen[animal_id] {
seen[animal_id] = true
temp = append(temp, animal_id)
}
animal_ids = append(animal_ids, animal_id)
}
if err := rows.Err(); err != nil {
@ -231,5 +211,5 @@ func (e *Encounter) EncounteredCats(user_id, num int) ([]int64, error) {
return nil, err
}
return temp, nil
return animal_ids, nil
}