简介
使用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
- }
复制代码 段落分词
使用第三方库进行分词
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 []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全文搜索的资料请关注脚本之家其它相关文章!
来源:互联网
免责声明:如果侵犯了您的权益,请联系站长(1277306191@qq.com),我们会及时删除侵权内容,谢谢合作! |
|