这是我参与「第三届青训营 -后端场」笔记创作活动的第2篇笔记。
本篇笔记对于搜索引擎项目中索引创建的逻辑与实现进行总结。
实现方案调研
- ElasticSearch是基于Lucene实现的索引构建与查询,Lucene的处理流程如下图所示:
创建索引的过程:
- 准备待索引的原文档,数据来源可能是文件、数据库或网络
- 这里项目实现中就是悟空数据集,若采用动态数据添加,那么就还需要加上爬虫模块获取网络数据进行扩充
- 对文档的内容进行分词组件处理,形成一系列的Term
- 索引组件对文档和Term处理,形成字典和倒排索引表
搜索索引的过程:
- 对查询语句(query)进行分词处理,形成一系列分词Term
- 根据倒排索引表查找出包含Term的文档,并进行合并形成符合结果的文档集
- 比对查询语句与各个文档相关性得分,并按照得分高低返回
项目实现
整体实现步骤
- 文档解析:
读取并解析csv文件,存储索引中间表和文档
- 索引创建与存储:
读取中间表,创建索引,存储索引
public class IndexGenerateRunner {
@Autowired
DocParser docParser;
@Autowired
IndexBuilder indexBuilder;
public void generate(String path) throws Exception {
// 1.1 从csv文件获取Doc
List<Doc> docList = CSVFileReader.readFile(path);
// 1.2 解析和存储文档
docParser.parse(docList);
// 2. 构建索引并存储
indexBuilder.buildIndexes();
}
}
BM25(搜索文本与文档关联度计算)
算法整体实现步骤
-
BM25算法用于计算一条搜索文本(可分为多个分词)与一个文档的匹配程度。
-
算法可分为三部分:
- 分词权重
- 分词和一个文档的关联度
- 分词与搜索文本的关联度(可选,对于长query需要)
- 算法所需参数
- 计算分词权重所需参数:1-总文档数,2-包含当前分词的文档的个数
- 计算分词和单个文档关联度所需参数:3-分词在该文档中的词频,4-当前文档的文档长度,5-所有文档的平均长度(文档长度的计算有两种方式:a. 文档中分词的数量(ElasticSearch和本项目采用);b. 文档字符个数)
- 计算分词与query的关联度所需参数:6-分词在query中的词频