提示:以下是本篇文章正文内容,Java系列学习将会持续更新
该项目类似于百度搜索引擎,在搜索框内输入一个 Java API 文档的关键字,对后端发出请求,后端将处理后的若干条查询结果返回给前端展示,并且按照一定的权重排序展示出来。每条搜索结果包含了标题、描述、URL,点击标题可以跳转到官方文档。
- 开发环境:IDEA、Maven、JDK 1.8、MySQL
- 相关技术:正排索引、倒排索引、分词技术、线程池、Spring Boot、JSON、Ajax
- 本地资源:Java API 文档 官方文档下载地址
项目主要分为3个模块:
- 索引模块:扫描本地 API 文档,分析内容(使用 Ansj 分词技术),构建正排+倒排索引;
- 搜索模块:输入查询词,基于倒排索引检索,根据分词权重+正排索引,展示查询结果;
- 前端模块:编写简单页面,对搜索结果作 CSS 布局,结合标签跳转到对应的 API 文档;
回到目录…
引入 ansj 依赖,将本地的 API 文档 进行分词处理,以便计算每个词的权重。
将分出来的词,放入 List 中。
正向索引就是:通过title(文档ID),去找value(目标文档),然后确定出包含的 文档 URL、content,将这些文档展示给用户。 正排索引的表中,tilte 是不重复的,每一个 title 对应唯一的 URL 和 content。 构建: 遍历每个文档的标题,并且存储其 URL 和 content。
如何提取本地的.html文档的内容? 使用 Java 正则表达式 去除HTML文件中的<标签>, 只保留文本格式。
倒排索引就是:通过value(关键词),去找key(文档ID),然后将找到的结果,即这些文档,展示给用户; 倒排索引的表中,(word, weight) 的组合是不重复的,每一组合都会有对应的文档ID,单词权重。 构建: 遍历每个文档中的所有词,每个文档插入 条数据到表中,。
如何计算单词的权重? 因为按照用户的搜索逻辑来说,文档标题的权重是自然要比内容中的单词权重高一些的。所以在计算时,适当的给标题提高权重。
回到目录…
- 键入 关键词,先对 query 进行分词,得到 。
- q 中可能出现多个关键词。针对每个关键词去倒排索引中查找,每个关键词都有若干条结果,把所有结果添加到 List中。
- 再对 List 中的所有结果,根据权重值排倒序(权重值高的靠前)。
- 此时,将所有结果以 JSON 的格式传递给前端,前端进行分页展示。 每页包含20条结果,每条结果包含标题、内容()、URL。
回到目录…
- 我们使用的数据库是 MySQL 。
- 我们在学习过 Spring 后,我们为了代码的便洁,不再采用传统的 JDBC 操作,而是引入了 MyBatis 。
出现的问题: 由于数据量非常大,导致构建索引的过程非常耗时,同时搜索时性能也比较差。
优化的过程:
-
最开始 —— 单线程+当行插入——耗时>3小时。
-
第一次优化:单线程+批量插入——耗时约3分钟。 使用 的方式执行 SQL 语句。 原因:单纯的 的使用,无法完成SQL的批量插入。 正排索引每次插入10条,因为正排索引的单条数据量就比较大(包含了文本内容)。 倒排索引每次插入10000条,单条数据量小。
- 第二次优化:多线程+批量插入——耗时约16秒。
- 第三次优化:在构建好的倒排索引表中,添加索引关联到 word 和 weight。
回到目录…
项目访问地址:http://1.15.76.95:8019
主页:
查询结果页:
点击跳转到官方文档:
回到目录…
- 前端页面的优化。
- 分词技术不够好,有些连续的单词没必要分,有些分出来的词没有意义,应该舍弃。
- 搜索不够好:目前不具备模糊查询的效果。
- 应该添加过滤器 搜索引擎过滤器:许多搜索引擎(例如Google和Bing)都为用户提供了打开安全过滤器的选项。激活此安全过滤器后,它会过滤掉所有搜索结果中的不适当链接。如果用户知道具有显式内容或成人内容的网站的实际网址,则他们可以在不使用搜索引擎的情况下访问该内容。一些提供商提供面向儿童的引擎版本。
回到目录…