• 设为首页
  • 收藏本站
  • 积分充值
  • VIP赞助
  • 手机版
  • 微博
  • 微信
    微信公众号 添加方式:
    1:搜索微信号(888888
    2:扫描左侧二维码
  • 快捷导航
    福建二哥 门户 查看主题

    golang使用redis实现全文搜索功能详解

    发布者: 娅水9213 | 发布时间: 2025-8-14 05:33| 查看数: 36| 评论数: 0|帖子模式

    简介

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

    实现思路

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

    具体实现


    文章分段

    文章段落表结构
    1. type TextModel struct {
    2.     gorm.Model
    3.     ArticleID uint   `json:"articleID"`
    4.     Head      string `json:"head"`
    5.     Body      string `json:"body"`
    6. }
    复制代码
    分段函数
    1. //这里因为我的项目里出现了循环导包,所以没有使用gorm的映射表进行处理
    2. type TextModel struct {
    3.     ArticleID uint   `json:"article_id"`
    4.     Head      string `json:"head"`
    5.     Body      string `json:"body"`
    6. }

    7. func MdContentTransformation(id uint, title string, content string) (list []TextModel) {
    8.         lines := strings.Split(content, "\n")
    9.         var headList []string
    10.         var bodyList []string
    11.         var body string
    12.         headList = append(headList, title)
    13.         var flag bool
    14.         for _, line := range lines {
    15.                 if strings.HasPrefix(line, "```") {
    16.                         flag = !flag
    17.                 }
    18.                 if !flag && strings.HasPrefix(line, "#") {
    19.                         // 标题行
    20.                         headList = append(headList, getHead(line))
    21.                         if strings.TrimSpace(body) != "" {
    22.                                 bodyList = append(bodyList, getBody(body))
    23.                         }
    24.                         body = ""
    25.                         continue
    26.                 }
    27.                 body += line
    28.         }
    29.         if body != "" {
    30.                 bodyList = append(bodyList, getBody(body))
    31.         }
    32.         if len(headList) > len(bodyList) {
    33.                 bodyList = append(bodyList, "")
    34.         }

    35.         if len(headList) != len(bodyList) {
    36.                 log.Errorf("headList与bodyList 不一致 \n headList:%q  %d\\\n bodyList: %q  %d\n", headList, len(headList), bodyList, len(bodyList))
    37.                 return
    38.         }
    39.     for i := 0; i < len(headList); i++ {
    40.             list = append(list, TextModel{
    41.             ArticleID: id,
    42.             Head:      headList[i],
    43.             Body:      bodyList[i],
    44.         })
    45.     }
    46.     return
    47. }

    48. func getHead(head string) string {
    49.     s := strings.TrimSpace(strings.Join(strings.Split(head, " ")[1:], " "))
    50.     return s
    51. }

    52. func getBody(body string) string {
    53.     body = strings.TrimSpace(body)
    54.     return body
    55. }
    复制代码
    段落分词

    使用第三方库进行分词
    https://github.com/go-ego/gse
    第三方库下载
    1. go get -u github.com/go-ego/gse
    复制代码
    库初始化
    1. func InitGse() {
    2.     newGse, _ := gse.New()
    3.     global_gse.Gse = newGse
    4. }
    复制代码
    分词函数
    1. func textParticiple(textList ...string) (words []string) {
    2.     for _, text := range textList {
    3.         word := global_gse.Gse.CutSearch(text, true)
    4.         words = append(words, word...)
    5.     }
    6.     return
    7. }
    复制代码
    把分过的词保存到到redis中

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

    通过将文本分词过后的查询词语获取一个段落集合
    1. func GetTextSearchIndex(text string) []string {
    2.     //分词
    3.     words := global_gse.Gse.CutSearch(text, true)
    4.     var _words []string
    5.     for _, word := range words {
    6.         _words = append(_words, fmt.Sprintf("text_%s", word))
    7.     }
    8.     vals, _ := global.Redis.SUnion(_words...).Result()
    9.     return vals
    10. }
    复制代码
    根据查到id列表查询数据库
    1. idList := redis_article.GetTextSearchIndex(cr.Key)
    2. query := global.DB.Where("id in ?", idList)
    复制代码
    后续处理,使搜索的文字有高亮提示
    可以将搜索的文字套在特定的标签中然后再返回信息
    以上就是golang使用redis实现全文搜索功能详解的详细内容,更多关于go redis全文搜索的资料请关注脚本之家其它相关文章!

    来源:互联网
    免责声明:如果侵犯了您的权益,请联系站长(1277306191@qq.com),我们会及时删除侵权内容,谢谢合作!

    最新评论

    QQ Archiver 手机版 小黑屋 福建二哥 ( 闽ICP备2022004717号|闽公网安备35052402000345号 )

    Powered by Discuz! X3.5 © 2001-2023

    快速回复 返回顶部 返回列表