这是我参与「第三届青训营 -后端场」笔记创作活动的第5篇笔记
一、项目概览
项目介绍
-
SimpleSearch是一个基于Java开发的单机图文搜索服务,可以实现百万级数据毫秒级查询。
- 搜索方面,支持文本搜索和以文搜图、关键词过滤以及相关搜索;
- 用户方面,提供用户管理与收藏夹功能;
- 同时,内置多级缓存以优化查询性能。
- 项目地址:http://47.104.4.41
- Github地址:github.com/ningowo/sim…
名词解释
业务命名
-
分词
- 把完整的查询query分成的,一个或多个用于索引和查询的词
-
索引
- 原始文档解析得到的,用于加快对query的查询。kv形式,key=分词,value=[包含这个分词的文档的id,分词权重*分词文档关联度]
专业名词
-
TF-IDF
- 词频 TF(Term Frequency),逆文本频率指数 IDF(Inverse Dcument Frequency) ,意思是文本越短其中出现的词越有代表性
-
BM25
- “在TF-IDF的基础上增加了几个可调节的参数,使得它在应用上更加灵活和强大”(TF-IDF和BM25)
项目概览
项目使用jdk11,基于SpringBoot进行开发。搜索服务中,业务层和引擎层中都使用Redis作为缓存,搜索引擎层使用MongoDB存储索引和文档;用户服务使用Mysql储存用户信息。
架构图
数据库表
索引存储(MongoDB)
中间表1 word_temp
{
_id: "word1",
doc_info_list: [
{
doc_id: 012abc34567L,
freq: 0
}
]
}
中间表2 doc_length
{
_id: 0L(是doc_id),
doc_len: 0,
}
结果表 word_doc_corr
{
_id: "word1",
doc_info_list: [
{
doc_id: 0L,
corr: "1.234"
}
]
}
文档存储(MongoDB)
key = docId, value = doc
缓存(Redis)
分词索引和query结果
搜索引擎
索引创建
整体实现步骤
- 文档解析:
读取并解析csv文件,存储索引中间表和文档
- 索引创建与存储:
读取中间表,创建索引,存储索引
BM25(搜索文本与文档关联度计算)
算法整体实现步骤
-
BM25算法用于计算一条搜索文本(可分为多个分词)与一个文档的匹配程度。
-
算法可分为三部分:
- 分词权重
- 分词和一个文档的关联度
- 分词与搜索文本的关联度(可选,对于长query需要)
- 算法所需参数
- 计算分词权重所需参数:1-总文档数,2-包含当前分词的文档的个数
- 计算分词和单个文档关联度所需参数:3-分词在该文档中的词频,4-当前文档的文档长度,5-所有文档的平均长度(文档长度的计算有两种方式:a. 文档中分词的数量(ElasticSearch和本项目采用);b. 文档字符个数)
- 计算分词与query的关联度所需参数:6-分词在query中的词频