- 分词器
- 用处:对词语进行分词
- 实现方式:使用gojieba进行分词
- 索印器
- 用处:通过词语找到有关联的文档
- 实现方式利用
BM25算法
计算词语与每个文档的相似性,从而生成一个词语到文档的倒排索引(具体过程见【项目流程】部分说明)
- 排序器
- 用处:用户输入查询词后,根据倒排索引得到和这个词语有关联的文档。然后根据排序器按关联度从高到低排序,并返回到前端进行渲染
- 实现:通过实现sort接口实现自定义排序
- 前后端
- 用处:用户在前端页面搜索框发送请求到后端后,后端根据
url
地址调用相应的函数进行处理 - 实现方式:使用go自带的http包"net/http"处理前端发来的请求
- 用处:用户在前端页面搜索框发送请求到后端后,后端根据
- 项目启动
- 新开协程生成倒排索引表
- 具体来说,先读取Excel数据,存储成一个
[]string
数组input
- 分词器对数组里的句子进行分词。然后把所有拆分好的词存到一个
[]string
数组segmentWords,然后传给索印器。比如input[0] = ["语言程序设计"]
会得到成segmentWords[0] = ["语言","程序","设计"]
- 索印器拿到,根据
bm25算法
算出每个拆分词,和原来未拆分的所有句子(称为"文档")的关联性,然后保存为一个倒排索引表Bm25Value
,比如Bm25Value[0][1][1]
代表 第0
个分词和第1
个文档的关联性分数
- 具体来说,先读取Excel数据,存储成一个
- 倒排索引表建立的同时,一边处理后端服务器其他逻辑
- 倒排索引表建立完成后,通过channel发送信号,主协程收到信号结束阻塞,完成最后工作后服务器启动完成
- 接下来,用户在前段搜索框输入
"计算机视觉"
,发送Ajax请求到后端。 - 后端拿到
从json里拿到query = "计算机视觉"
后,先调用分词器Segmenter
进行全模式分词,得到["计算机","视觉","计算机视觉"]
,然后从倒排索引表里查找和这三个词有关联的文档,这些文档返回到前端,前端再渲染到页面
-
倒排索引表是基于词语与文档的关联性建立的,为了实现这一点,项目使用BM25算法来计算词语与文档的关联性
-
用户输入查询词query后,需对query的分词结果进行组合排列。比如:输入的词语为
“计算机视觉”
,此时如果简单调用分词器进行分词会得到["计算机","视觉"]
两个词,得到也只会是和这两个词有关联的文档。但以生活经验来说,应该是用["计算机","视觉","计算机视觉"]
这个三个词去查询文档才对,并且和"计算机视觉"
关联的文档应该具有更高的优先级。- 解决方法:利用DFS回溯对分词结果进行紧邻全排序。比如
[1,2,3]
,会得到[1,2,3,12,23,123]
多种结果,然后拿这些排列过的词再去查关联文档。 - 但后面发现gojieba提供全模式分词,也能实现这个效果。而且实验发现gojieba的速度更快,所以最后改用gojieba了
- 解决方法:利用DFS回溯对分词结果进行紧邻全排序。比如
- 没线上部署
- 原因:从数据集读取所有数据(5万条)后再生成倒排索引表,由于倒排索引表存在内存中,需要很大的内存。我的电脑内存为32G,加上虚拟内存总共64G仍然会爆内存。而租高配置的服务器费用较高,所以暂时部署上去
- 上面说过以生活经验来说,输入
"计算机视觉"
应该是用["计算机","视觉","计算机视觉"]
这个三个词去查询文档,并且和"计算机视觉"
关联的文档应该具有更高的优先级,暂时还没实现给"计算机视觉"
关联的文档更高的优先级 - 暂时还没实现相关搜索
- 时间问题,后面再完善
- 图片搜索
- 这个其实实现不难,因为数据集有关联文档的图片,所以可以通过
id
直接拿到对应这个文档的图片,然后把图片渲染到页面上。 - 但还是因为人手和时间的关系,来不及弄前端的部分
- 这个其实实现不难,因为数据集有关联文档的图片,所以可以通过
- 还没有实现【过滤功能】