欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 汽车 > 维修 > golang使用redis实现全文搜索

golang使用redis实现全文搜索

2025/2/22 2:24:19 来源:https://blog.csdn.net/m0_70982551/article/details/145657801  浏览:    关键词:golang使用redis实现全文搜索

简介

使用redis实现全部文章精确到段落的搜索

实现思路

  • 文章分段,使用一张表单独记录下段落信息
  • 段落分词,把段落划分成词
  • 分词后使用有序集合记录到redis中,每个词语后记录含有该分词的段落ID集
  • 使用一个哈希键记录下每个段落的分词,用于分词信息的删除
  • 查询时先分词,再根据分的词把分词查到的对应的段落
  • 返回结果

具体实现

文章分段

  • 文章段落表结构
type TextModel struct {gorm.ModelArticleID uint   `json:"articleID"`Head      string `json:"head"`Body      string `json:"body"`
}
  • 分段函数
//这里因为我的项目里出现了循环导包,所以没有使用gorm的映射表进行处理
type TextModel struct {ArticleID uint   `json:"article_id"`Head      string `json:"head"`Body      string `json:"body"`
}func MdContentTransformation(id uint, title string, content string) (list []TextModel) {lines := strings.Split(content, "\n")var headList []stringvar bodyList []stringvar body stringheadList = append(headList, title)var flag boolfor _, line := range lines {if strings.HasPrefix(line, "```") {flag = !flag}if !flag && strings.HasPrefix(line, "#") {// 标题行headList = append(headList, getHead(line))if strings.TrimSpace(body) != "" {bodyList = append(bodyList, getBody(body))}body = ""continue}body += line}if body != "" {bodyList = append(bodyList, getBody(body))}if len(headList) > len(bodyList) {bodyList = append(bodyList, "")}if len(headList) != len(bodyList) {log.Errorf("headList与bodyList 不一致 \n headList:%q  %d\\\n bodyList: %q  %d\n", headList, len(headList), bodyList, len(bodyList))return}for i := 0; i < len(headList); i++ {list = append(list, TextModel{ArticleID: id,Head:      headList[i],Body:      bodyList[i],})}return
}func getHead(head string) string {s := strings.TrimSpace(strings.Join(strings.Split(head, " ")[1:], " "))return s
}func getBody(body string) string {body = strings.TrimSpace(body)return body
}

段落分词

  • 使用第三方库进行分词
    https://github.com/go-ego/gse
    第三方库下载
go get -u github.com/go-ego/gse
  • 库初始化
func InitGse() {newGse, _ := gse.New()global_gse.Gse = newGse
}
  • 分词函数
func textParticiple(textList ...string) (words []string) {for _, text := range textList {word := global_gse.Gse.CutSearch(text, true)words = append(words, word...)}return
}

把分过的词保存到到redis中

  • 使用redis集合每个词对应的段落ID
func SetTextSearchIndex(textID uint, words []string) {for _, word := range words {if word == "" {continue}global.Redis.SAdd(fmt.Sprintf("text_%s", word), textID)}
}
  • 使用哈希键记录每个文章对应的段落和词语信息,用于信息删除
func SetTextSearchWords(articleID uint, textID uint, words []string) {_words, _ := json.Marshal(words)global.Redis.HSet(fmt.Sprintf("text_search_words_%d", articleID), strconv.Itoa(int(textID)), _words)
}

查询操作

  • 通过将文本分词过后的查询词语获取一个段落集合
func GetTextSearchIndex(text string) []string {//分词words := global_gse.Gse.CutSearch(text, true)var _words []stringfor _, word := range words {_words = append(_words, fmt.Sprintf("text_%s", word))}vals, _ := global.Redis.SUnion(_words...).Result()return vals
}
  • 根据查到id列表查询数据库
idList := redis_article.GetTextSearchIndex(cr.Key)
query := global.DB.Where("id in ?", idList)

后续处理,使搜索的文字有高亮提示

  • 可以将搜索的文字套在特定的标签中然后再返回信息

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词