用go构建个简单的搜索(八) 通过BM25构建简单关键词搜索

2023年 7月 13日 8.2k 0

上篇: 用go构建个简单的搜索(七) BM25打分

流程概述

graph TD
A(加载文档) --> b[切词]
b[切词]     --> c[统计文档和词频关系]

d[BM25关键词打分] --> e[打分排序]
f[关键词查询]

当前处理点和遇到的问题

  • demo是用map处理的,map好处是可以用到k-v数据库作为持久化
  • go的map根据value排序 map[int]float32=》文档:得分
  • go中map的v是结构体数据修改

困惑的地方

  • 文档是不停增长的,但是BM25打分依赖文档总数和至少出现一次的关键词总数 该如何处理比较好点
  • 如何定义一个父类的结构体,实现自定义的子结构体数据处理

测试效果

image.png

代码demo

type docWord struct {
	word_s     string          //关键词
	word_tf    map[int]int     //文档中的词频 key文档编号
	word_score map[int]float32 //文档中得分   key文档编号
	score_sort []scoreSort     //得分排序
}

//得分排序
type scoreSort struct {
	id    int
	score float32
}
func TestBM26(t *testing.T) {
        //测试每行作为一个文档
	str, isTrue := loadFileByLine("D:/开发语言/文章/小说/活着2.txt")
	if isTrue {
		avgLen := getAVG(str)                      //得到文档平均长度
		var docWordArry = make(map[string]docWord) //切词对应的数据文档
		//单词 文档 打分
		for i, s := range str {
			wordTF := getSplicWordTF(s)//切词
			//至少出现一次文档数 得到词频
			for word := range wordTF {
				_, ok := docWordArry[word]
				if ok {
					docWordArry[word].word_tf[i]++
				} else {
					docWordArry[word] = docWord{
						word_s:     word,
						word_tf:    make(map[int]int),
						word_score: make(map[int]float32),
						score_sort: make([]scoreSort, 0),
					}
					docWordArry[word].word_tf[i] = 1
				}
			}
		}

		for w := range docWordArry {
			dw := docWordArry[w]
			for index := range dw.word_tf {
				//打分
				dw.word_score[index] = BM25(float32(dw.word_tf[index]), float32(len([]rune(str[index]))), avgLen, float32(len(str)), float32(len(dw.word_tf)))
				dw.score_sort = append(dw.score_sort, scoreSort{index, dw.word_score[index]})
			}
			// if "福贵" == w {
                        //得分排序
			sort.Slice(dw.score_sort, func(i, j int) bool {
				return dw.score_sort[i].score > dw.score_sort[j].score // 降序
			})
			// }
			docWordArry[w] = dw //这里有个map修改值得问题
		}

		search := docWordArry["福贵"]
		for _, index := range search.score_sort {
			fmt.Printf("%sn文档ID:%d,词:%s,打分:%fn", str[index.id], index.id, search.word_s, search.word_score[index.id])
		}
	}
}

相关文章

如何删除WordPress中的所有评论
检查WordPress服务器磁盘使用情况的7种简便方法(查找大文件和数据)
如何更改WordPress常量FS_METHOD
如何为区块编辑器、Elementor等构建WordPress文章模板
如何彻底地删除WordPress主题及相关内容
如何使用WordPress搭建一个内网

发布评论