目录
- 简介
- 实现思路
- 具体实现
- 文章分段
- 段落分词
- 把分过的词保存到到Redis中
- 查询操作
简介
使用redis实现全部文章精确到段落的搜索
实现思路
文章分段,使用一张表单独记录下段落信息
段落分词,把段落划分成词
分词后使用有序集合记录到redis中,每个词语后记录含有该分词的段落ID集
使用一个哈希键记录下每个段落的分词,用于分词信息的删除
查询时先分词,再根据分的词把分词查到的对应的段落
返回结果
具体实现
文章分段
文章段落表结构
type TextModel struct { gorm.Model ArticleID 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 []string var bodyList []string var body string headList = append(headList, title) var flag bool for _, 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 }
段落分js词
使用第三方库进行分词
https://github.com/go-ego/gse
编程客栈第三方库下载
g编程o get -u github.com/go-ego/gse
库初始化
func InitGse() { newGse, _ := gse.New() global_gse.Gse = newGse }
分词函数
func texjstParticiple(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 []string for _, 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)
后续处理,使搜索的文字有高亮提示
可以将搜索的文字套在特定的标签中然后再返回信息
以上就是golang使用redis实现全文搜索功能详解的详细内容,更多关于go redis全文搜索的资料请关注编程客栈(www.devze.com)其它相关文章!
精彩评论