2021年大数据ELK(四):Lucene的美文搜索案例
全网最详细的大数据ELK文章系列,强烈建议收藏加关注!
新文章都已经列出历史文章目录,帮助大家回顾前面的知识重点。
目录
系列历史文章
美文搜索案例
一、需求
二、准备工作
1、创建IDEA项目
2、创建父工程
3、添加lucene模块
4、导入Maven依赖
5、创建包和类
6、导入文章数据
三、建立索引库
1、实现步骤
2、参考代码
3、执行效果
四、关键字查询
1、需求
2、准备工作
3、开发步骤
4、参考代码
5、执行效果
五、搜索词语问题
六、分词器与中文分词器
七、使用IK分词器重构案例
1、准备工作
2、实现步骤
3、参考代码
4、执行效果
5、问题
八、句子搜索
1、实现步骤
2、参考代码
3、执行效果
系列历史文章
2021年大数据ELK(六):安装Elasticsearch
2021年大数据ELK(五):Elasticsearch中的核心概念
2021年大数据ELK(四):Lucene的美文搜索案例
2021年大数据ELK(三):Lucene全文检索库介绍
2021年大数据ELK(二): Elasticsearch简单介绍
2021年大数据ELK(一):集中式日志协议栈Elastic Stack简介
美文搜索案例
一、需求
在资料中的文章文件夹中,有很多的文本文件。这里面包含了一些非常有趣的软文。而我们想要做的事情是,通过搜索一个关键字就能够找到哪些文章包含了这些关键字。例如:搜索「hadoop」,就能找到hadoop相关的文章。
需求分析:
要实现以上需求,我们有以下两种办法:
- 用户输入搜索关键字,然后我们挨个读取文件,并查找文件中是否包含关键字
- 我们先挨个读取文件,对文件的文本进行分词(例如:按标点符号),然后建立索引,用户输入关键字,根据之前建立的索引,搜索关键字。
很明显,第二种方式要比第一种效果好得多,性能也好得多。所以,我们下面就使用Lucene来建立索引,然后根据索引来进行检索。
二、准备工作
1、创建IDEA项目
此处在IDEA中的工程模型如下:
2、创建父工程
groupId |
cn.it |
artifactId |
es_parent |
3、添加lucene模块
groupId |
cn.it |
artifactId |
lucene_op |
4、导入Maven依赖
导入依赖到lucene_op的pom.xml
<dependencies><!-- lucene核心类库 --><dependency><groupId>org.apache.lucene</groupId><artifactId>lucene-core</artifactId><version>8.4.0</version></dependency><dependency><groupId>org.apache.lucene</groupId><artifactId>lucene-analyzers-common</artifactId><version>8.4.0</version></dependency><dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.6</version></dependency><dependency><groupId>com.jianggujin</groupId><artifactId>IKAnalyzer-lucene</artifactId><version>8.0.0</version></dependency></dependencies><build><plugins><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-compiler-plugin</artifactId><version>3.1</version><configuration><source>1.8</source><target>1.8</target></configuration></plugin></plugins></build>
5、创建包和类
- 在java目录创建 cn.it.lucene 包结构
- 创建BuildArticleIndex类
6、导入文章数据
- 在 lucene_op 模块下创建名为 data 的目录,用来存放文章文件
- 在 lucene_op 模块下创建名为 index 的目录,用于存放最后生成的索引文件
- 将资料/文章目录下的txt文件复制到 data 目录中
三、建立索引库
1、实现步骤
- 构建分词器(StandardAnalyzer)
- 构建文档写入器配置(IndexWriterConfig)
- 构建文档写入器(IndexWriter,注意:需要使用Paths来)
- 读取所有文件构建文档
- 文档中添加字段
字段名 |
类型 |
说明 |
file_name |
TextFiled |
文件名字段,需要在索引文档中保存文件名内容 |
content |
TextFiled |
内容字段,只需要能被检索,但无需在文档中保存 |
path |
StoredFiled |
路径字段,无需被检索,只需要在文档中保存即可 |
- 写入文档
- 关闭写入器
2、参考代码
package cn.it.lucene;import java.io.File;
import java.io.IOException;
import java.nio.file.Paths;
import org.apache.commons.io.FileUtils;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.StoredField;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.store.FSDirectory;public class BuildArticleIndex {public static void main(String[] args) throws IOException {// 1. 构建分词器(StandardAnalyzer)StandardAnalyzer standardAnalyzer = new StandardAnalyzer();// 2. 构建文档写入器配置(IndexWriterConfig)IndexWriterConfig indexWriterConfig = new IndexWriterConfig(standardAnalyzer);// 3. 构建文档写入器(IndexWriter)IndexWriter indexWriter = new IndexWriter(FSDirectory.open(Paths.get("E:\\project\\java\\elk\\es_parent\\lucene_op\\index")), indexWriterConfig);// 4. 读取所有文件构建文档File articleDir = new File("E:\\project\\java\\elk\\es_parent\\lucene_op\\data");File[] fileList = articleDir.listFiles();for (File file : fileList) {// 5. 文档中添加字段Document docuemnt = new Document();docuemnt.add(new TextField("file_name", file.getName(), Field.Store.YES));docuemnt.add(new TextField("content", FileUtils.readFileToString(file, "UTF-8"), Field.Store.NO));docuemnt.add(new StoredField("path", file.getAbsolutePath() + "/" + file.getName()));// 6. 写入文档indexWriter.addDocument(docuemnt);}// 7. 关闭写入器indexWriter.close();}
}
3、执行效果
四、关键字查询
1、需求
输入一个关键字“心”,根据关键字查询索引库中是否有匹配的文档
2、准备工作
- 前提:基于文章文本文件,已经生成好了索引
- 在cn.it.lucene包下创建一个类KeywordSearch
3、开发步骤
- 使用DirectoryReader.open构建索引读取器
- 构建索引查询器(IndexSearcher)
- 构建词条(Term)和词条查询(TermQuery)
- 执行查询,获取文档
- 遍历打印文档(可以使用IndexSearch.doc根据文档ID获取到文档)
- 关键索引读取器
4、参考代码
package cn.it.lucene;import java.io.IOException;
import java.nio.file.Paths;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.store.FSDirectory;public class KeywordSearch {public static void main(String[] args) throws IOException {// 1. 构建索引读取器IndexReader indexReader = DirectoryReader.open(FSDirectory.open(Paths.get("E:\\project\\java\\elk\\es_parent\\lucene_op\\index")));// 2. 构建索引查询器IndexSearcher indexSearcher = new IndexSearcher(indexReader);// 3. 执行查询,获取文档TermQuery termQuery = new TermQuery(new Term("content", "心"));TopDocs topDocs = indexSearcher.search(termQuery, 50);ScoreDoc[] scoreDocArrary = topDocs.scoreDocs;// 4. 遍历打印文档for (ScoreDoc scoreDoc : scoreDocArrary) {int docId = scoreDoc.doc;Document document = indexSearcher.doc(docId);System.out.println("文件名:" + document.get("file_name") + " 路径:" + document.get("path"));}indexReader.close();}
}
5、执行效果
五、搜索词语问题
上述代码,都是一个字一个字的搜索,但如果搜索一个词,例如:“情愿”,我们会发现,我们什么都搜索不出来。所以,接下来,我们还需要来解决搜索一个词的问题。
六、分词器与中文分词器
分词器是指将一段文本,分割成为一个个的词语的动作。例如:按照停用词进行分隔(的、地、啊、吧、标点符号等)。我们之前在代码中使用的分词器是Lucene中自带的分词器。这个分词器对中文很不友好,只是将一个一个字分出来,所以,就会从后出现上面的问题——无法搜索词语。
所以,基于该背景,我们需要使用跟适合中文的分词器。中文分词器也有不少,例如:
- Jieba分词器
- IK分词器
- 庖丁分词器
- Smarkcn分词器
等等。此处,我们使用比较好用的IK分词器来进行分词。
IK已经实现好了Lucene的分词器:https://github.com/wks/ik-analyzer
IKAnalyzer是一个开源的,基于java语言开发的轻量级的中文分词工具包。从2006年12月推出1.0版开始,IKAnalyzer已经推出了3个大版本。最初,它是以开源项目Luence为应用主体的,结合词典分词和文法分析算法的中文分词组件。新版本的 IKAnalyzer3.0则发展为面向Java的公用分词组件,独立于Lucene项目,同时提供了对Lucene的默认优化实现。 IKAnalyzer3.0特性: 采用了特有的“正向迭代最细粒度切分算法“,支持细粒度和最大词长两种切分模式;具有83万字/秒(1600KB/S)的高速处理能力。 采用了多子处理器分析模式,支持:英文字母、数字、中文词汇等分词处理,兼容韩文、日文字符 优化的词典存储,更小的内存占用。支持用户词典扩展定义 针对Lucene全文检索优化的查询分析器IKQueryParser(作者吐血推荐);引入简单搜索表达式,采用歧义分析算法优化查询关键字的搜索排列组合,能极大的提高Lucene检索的命中率。 |
七、使用IK分词器重构案例
1、准备工作
添加Maven依赖
<dependency><groupId>com.jianggujin</groupId><artifactId>IKAnalyzer-lucene</artifactId><version>8.0.0</version>
</dependency>
创建BuildArticleIndexByIkAnalyzer类
2、实现步骤
把之前生成的索引文件删除,然后将之前使用的StandardAnalyzer修改为IKAnalyzer。然后重新生成索引。
3、参考代码
package cn.it.lucene;import java.io.File;
import java.io.IOException;
import java.nio.file.Paths;
import org.apache.commons.io.FileUtils;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.StoredField;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.store.FSDirectory;
import org.wltea.analyzer.lucene.IKAnalyzer;public class BuildArticleIndexByIkAnalyzer {public static void main(String[] args) throws IOException {// 1. 构建分词器(StandardAnalyzer)IKAnalyzer ikAnalyzer = new IKAnalyzer();// 2. 构建文档写入器配置(IndexWriterConfig)IndexWriterConfig indexWriterConfig = new IndexWriterConfig(ikAnalyzer);// 3. 构建文档写入器(IndexWriter)IndexWriter indexWriter = new IndexWriter(FSDirectory.open(Paths.get("E:\\project\\java\\elk\\es_parent\\lucene_op\\index")), indexWriterConfig);// 4. 读取所有文件构建文档File articleDir = new File("E:\\project\\java\\elk\\es_parent\\lucene_op\\data");File[] fileList = articleDir.listFiles();for (File file : fileList) {// 5. 文档中添加字段Document docuemnt = new Document();docuemnt.add(new TextField("file_name", file.getName(), Field.Store.YES));docuemnt.add(new TextField("content", FileUtils.readFileToString(file, "UTF-8"), Field.Store.NO));docuemnt.add(new StoredField("path", file.getAbsolutePath() + "/" + file.getName()));// 6. 写入文档indexWriter.addDocument(docuemnt);}// 7. 关闭写入器indexWriter.close();}
}
4、执行效果
5、问题
通过使用IK分词器进行分词,我们发现,现在我们的程序可以搜索词语了。但如果我们输入一句话:人生是一条河,我们想要搜索出来与其相关的文章。应该如何实现呢?
八、句子搜索
在cn.it.lucene 包下创建一个SentenceSearch类
1、实现步骤
要实现搜索句子,其实是将句子进行分词后,再进行搜索。我们需要使用QueryParser类来实现。通过QueryParser可以指定分词器对要搜索的句子进行分词。
2、参考代码
package cn.it.lucene;import java.io.IOException;
import java.nio.file.Paths;
import java.text.ParseException;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.store.FSDirectory;
import org.wltea.analyzer.lucene.IKAnalyzer;public class SentenceSearch {public static void main(String[] args) throws IOException {// 1. 构建索引读取器IndexReader indexReader = DirectoryReader.open(FSDirectory.open(Paths.get("D:\\project\\51.V8.0_NoSQL_MQ\\ElasticStack\\code\\es_parent\\lucene_op\\index")));// 2. 构建索引查询器IndexSearcher indexSearcher = new IndexSearcher(indexReader);// 3. 执行查询,获取文档QueryParser queryParser = new QueryParser("content", new IKAnalyzer());TopDocs topDocs = null;try {topDocs = indexSearcher.search(queryParser.parse("人生是一条河"), 50);} catch (org.apache.lucene.queryparser.classic.ParseException e) {e.printStackTrace();}ScoreDoc[] scoreDocArrary = topDocs.scoreDocs;// 4. 遍历打印文档for (ScoreDoc scoreDoc : scoreDocArrary) {int docId = scoreDoc.doc;Document document = indexSearcher.doc(docId);System.out.println("文件名:" + document.get("file_name") + " 路径:" + document.get("path"));}indexReader.close();}
}
3、执行效果
-
2021年大数据ELK(四):Lucene的美文搜索案例相关推荐
- 2021年大数据ELK(三):Lucene全文检索库介绍
全网最详细的大数据ELK文章系列,强烈建议收藏加关注! 新文章都已经列出历史文章目录,帮助大家回顾前面的知识重点. 目录 系列历史文章 一.什么是全文检索 1.结构化数据与非结构化数据 2.搜索结构化 ...
- 2021年大数据ELK(八):Elasticsearch安装IK分词器插件
全网最详细的大数据ELK文章系列,强烈建议收藏加关注! 新文章都已经列出历史文章目录,帮助大家回顾前面的知识重点. 目录 系列历史文章 安装IK分词器 一.下载Elasticsearch IK分词器 ...
- 2021年大数据ELK(六):安装Elasticsearch
全网最详细的大数据ELK文章系列,强烈建议收藏加关注! 新文章都已经列出历史文章目录,帮助大家回顾前面的知识重点. 目录 系列历史文章 安装Elasticsearch 一.创建普通用户 二.为普通用户 ...
- 2021年大数据ELK(五):Elasticsearch中的核心概念
全网最详细的大数据ELK文章系列,强烈建议收藏加关注! 新文章都已经列出历史文章目录,帮助大家回顾前面的知识重点. 目录 系列历史文章 Elasticsearch中的核心概念 一.索引 index 二 ...
- 2021年大数据ELK(二):Elasticsearch简单介绍
全网最详细的大数据ELK文章系列,强烈建议收藏加关注! 新文章都已经列出历史文章目录,帮助大家回顾前面的知识重点. 目录 系列历史文章 一.Elasticsearch简介 1.介绍 2.创始人 二.E ...
- 2021年大数据ELK(一):集中式日志协议栈Elastic Stack简介
全网最详细的大数据ELK文章系列,强烈建议收藏加关注! 新文章都已经列出历史文章目录,帮助大家回顾前面的知识重点. 目录 系列历史文章 一.简介 二.ELK 协议栈介绍及体系结构 三.集中式日志协议栈 ...
- 2021年大数据ELK(二十四):安装Kibana
全网最详细的大数据ELK文章系列,强烈建议收藏加关注! 新文章都已经列出历史文章目录,帮助大家回顾前面的知识重点. 安装Kibana 在Linux下安装Kibana,可以使用Elastic stack ...
- 2021年大数据ELK(二十六):探索数据(Discovery)
全网最详细的大数据ELK文章系列,强烈建议收藏加关注! 新文章都已经列出历史文章目录,帮助大家回顾前面的知识重点. 目录 探索数据(Discovery) 一.使用探索数据功能 二.导入更多的Apach ...
- 2021年大数据ELK(十七):Elasticsearch SQL 订单统计分析案例
全网最详细的大数据ELK文章系列,强烈建议收藏加关注! 新文章都已经列出历史文章目录,帮助大家回顾前面的知识重点. 目录 订单统计分析案例 一.案例介绍 二.创建索引 三.导入测试数据 四.统计不同支 ...
最新文章
- windows如何安装python-手把手教你如何在windows系统安装python?
- 关于code reiview
- mysql实例化_mysql多实例实例化数据库
- idea 注释模板_常用的模板函数
- 桌面计算机怎么覆盖文件,恢复被覆盖的文件_恢复被覆盖的桌面文件
- 获取文本上每个字符出现的次数并保留在map中,再将map中的数据写入文件
- 修改mysql数据存放路径
- 后台数据量太大传输慢_哪些因素会导致慢查询?
- 创建、复制、删除、重命名、获取文件名等常用的批处理bat命令
- 解决checkra1n越狱失败及越狱后AFC2失效问题
- 搭建安卓开发环境并测试运行安卓开发环境
- word中图片为嵌入式格式时显示不全_word插入图片嵌入式 word图片显示不全
- java 线程的插队运行_java笔记--线程的插队行为
- mysql中获取时间的年月日_Mysql获取系统时间,年,月,日
- ps修改头发颜色----和修改衣服颜色-------给褶皱的衣服添加图案
- LED显示屏和液晶显示屏有什么区别?
- unity urp内置lit材质源码解析(中)
- 游戏服务端框架之本服实时排行榜
- (Java实现) 过河卒
- SSL证书链不完整(或不被客户端信任)问题,填坑
热门文章
- 2021年大数据ELK(三):Lucene全文检索库介绍