From 5f5eb22b390746c9c85964e9e886393ba386fc2c Mon Sep 17 00:00:00 2001 From: douxu Date: Thu, 25 Sep 2025 16:39:45 +0800 Subject: [PATCH] optimize code of redis search query --- constants/keys.go | 17 +++++- model/object.go | 135 ++++++++++++++++++++++++++++------------------ 2 files changed, 99 insertions(+), 53 deletions(-) diff --git a/constants/keys.go b/constants/keys.go index 6180b37..52268d7 100644 --- a/constants/keys.go +++ b/constants/keys.go @@ -5,5 +5,20 @@ const ( // RedisAllGridSetKey define redis set key which store all grid keys RedisAllGridSetKey = "grid_keys" // RedisSpecGridZoneSetKey define redis set key which store all zone keys under specific grid - RedisSpecGridZoneSetKey = "grid_%s_zones_keys" // grid_{grid}_zones_keys + RedisSpecGridZoneSetKey = "grid_%s_zones_keys" + + // RedisAllZoneSetKey define redis set key which store all zone keys + RedisAllZoneSetKey = "zone_keys" + // RedisSpecZoneStationSetKey define redis set key which store all station keys under specific zone + RedisSpecZoneStationSetKey = "zone_%s_stations_keys" + + // RedisAllStationSetKey define redis set key which store all station keys + RedisAllStationSetKey = "station_keys" + // RedisSpecStationComponentSetKey define redis set key which store all component keys under specific station + RedisSpecStationComponentSetKey = "station_%s_components_keys" + + // RedisAllComponentSetKey define redis set key which store all component keys + RedisAllComponentSetKey = "component_keys" + // RedisSpecComponentSetKey define redis set key which store all component keys under specific zone + RedisSpecComponentSetKey = "zone_%s_components_keys" ) diff --git a/model/object.go b/model/object.go index f984e8a..efe2761 100644 --- a/model/object.go +++ b/model/object.go @@ -8,12 +8,13 @@ import ( "modelRT/constants" "modelRT/diagram" + "modelRT/logger" "github.com/RediSearch/redisearch-go/redisearch" ) -// RedisSearch define func of redis search by input string -func RedisSearch(ctx context.Context, input string) ([]string, error) { +// RedisSearchRecommend define func of redis search by input string and return recommend results +func RedisSearchRecommend(ctx context.Context, input string) ([]string, error) { rdb := diagram.GetRedisClientInstance() if input == "" { @@ -21,63 +22,78 @@ func RedisSearch(ctx context.Context, input string) ([]string, error) { return getAllGridKeys(ctx, constants.RedisAllGridSetKey) } - gridExist, err := rdb.SIsMember(ctx, constants.RedisAllGridSetKey, input).Result() - // TODO 处理err - fmt.Println(gridExist, err) + inputs := strings.Split(input, ".") + inputLen := len(inputs) - // TODO 判断input是否为一个完整的层级 - // 处理 input 不为空、不含有.并且 input 是一个完整的 grid key 的情况 - if strings.HasSuffix(input, ".") == false && gridExist { - return []string{"."}, nil - } - - // 处理 input 不为空并且以.结尾的情况 - if strings.HasSuffix(input, ".") == true { - setKey := fmt.Sprintf(constants.RedisSpecGridZoneSetKey, input) - return getSpecificZoneKeys(ctx, setKey) - } - - // // 处理 input 不为空、不含有.并且 input 是一个完整的 grid key 的情况 - // if strings.HasSuffix(input, ".") == false && gridExist { - // setKey := fmt.Sprintf(constants.RedisSpecGridZoneSetKey, input) - // return getSpecificZoneKeys(ctx, setKey) - // } - - // TODO 默认每次传递的带有.的前缀字符串一定正确 - if strings.HasSuffix(input, ".") { - // TODO 首先判断.后是否为空字符串,为空则返回上次层级下的所有key - // TODO 其次进行前缀匹配 - parentKey := strings.TrimSuffix(input, ".") - // 直接查询预存的下一级内容 - results, err := rdb.ZRange(ctx, "autocomplete:"+parentKey, 0, -1).Result() - fmt.Println(err) - return results, nil - } - - // TODO 处理前缀或模糊匹配 - // TODO 使用 RediSearch 的 FT.SUGGET 与Fuzzy标志进行前缀或模糊查询 ac := redisearch.NewAutocompleter("localhost:6379", "my-autocomplete-dict") - results, err := ac.SuggestOpts(input, redisearch.SuggestOptions{ - Num: 5, - Fuzzy: true, - WithScores: true, - WithPayloads: true, - }) - if err != nil { - fmt.Println(err) - } + switch inputLen { + case 1: + gridExist, err := rdb.SIsMember(ctx, constants.RedisAllGridSetKey, input).Result() + if err != nil { + logger.Error(ctx, "check grid key exist failed ", "grid_key", input, "error", err) + return []string{}, err + } - var terms []string - for _, result := range results { - terms = append(terms, result.Term) + if !gridExist { + results, err := ac.SuggestOpts(input, redisearch.SuggestOptions{ + // TODO 测试如何返回全部的可能模糊结果 + Num: 5, + Fuzzy: true, + WithScores: true, + WithPayloads: true, + }) + if err != nil { + logger.Error(ctx, "query info by fuzzy failed", "grid_key", input, "error", err) + return []string{}, err + } + + var grids []string + for _, result := range results { + grids = append(grids, result.Term) + } + // 返回模糊查询结果 + return grids, nil + } + + // 处理 input 不为空、不含有.并且 input 是一个完整的 grid key 的情况 + if strings.HasSuffix(input, ".") == false { + return []string{"."}, nil + } + + // 处理 input 不为空并且以.结尾的情况 + if strings.HasSuffix(input, ".") == true { + setKey := fmt.Sprintf(constants.RedisSpecGridZoneSetKey, input) + return getSpecificZoneKeys(ctx, setKey) + } + default: + lastToken := inputs[inputLen-1] + // TODO 判断queryKey是否是空值,空值则返回上一级别下的所有key + if lastToken == "" { + setKey := getConstantsKeyByLength(inputLen - 1) + targetSet := diagram.NewRedisSet(ctx, setKey, 10, true) + // TODO 将 SMembers 返回的值处理后返回 + targetSet.SMembers(setKey) + } + + querykey := lastToken + setKey := getConstantsKeyByLength(inputLen) + targetSet := diagram.NewRedisSet(ctx, setKey, 10, true) + exist, err := targetSet.SIsMember(setKey, querykey) + if err != nil { + logger.Error(ctx, "check keys exist failed", "set_key", setKey, "query_key", querykey, "error", err) + return []string{}, fmt.Errorf("check keys failed,%w", err) + } + if !exist { + fmt.Println("use fuzzy query") + } + return []string{}, nil } - // 返回结果 - return terms, nil + return []string{}, nil } func getAllGridKeys(ctx context.Context, setKey string) ([]string, error) { - // TODO 从redis set中获取所有的 grid key + // 从redis set 中获取所有的 grid key gridSets := diagram.NewRedisSet(ctx, setKey, 10, true) keys, err := gridSets.SMembers("grid_keys") if err != nil { @@ -87,7 +103,7 @@ func getAllGridKeys(ctx context.Context, setKey string) ([]string, error) { } func getSpecificZoneKeys(ctx context.Context, setKey string) ([]string, error) { - // TODO 从redis set中获取所有的 grid key + // TODO 从redis set 中获取指定 grid 下的 zone key zoneSets := diagram.NewRedisSet(ctx, setKey, 10, true) keys, err := zoneSets.SMembers("grid_keys") if err != nil { @@ -95,3 +111,18 @@ func getSpecificZoneKeys(ctx context.Context, setKey string) ([]string, error) { } return keys, nil } + +func getConstantsKeyByLength(inputLen int) string { + switch inputLen { + case 1: + return constants.RedisAllGridSetKey + case 2: + return constants.RedisAllZoneSetKey + case 3: + return constants.RedisAllStationSetKey + case 4: + return constants.RedisAllComponentSetKey + default: + return constants.RedisAllGridSetKey + } +}