目录
一、lucene是什么
lucene是一个全文检索框架,为我们的web应用提供丰富的快速的查询数据的一个开源个工具框架。用户可以使用该框架来实现自己应用的搜索功能。类似于淘宝,京东首页的搜索框功能实现。
二、lucene解决什么问题
在没有lucene该类似框架之前,我们一般的web应用搜索是使用数据库的模糊查询来实现相关搜索的功能
数据库层次的搜索
使用mysql的模糊搜索 like
1、性能:小数据量情况下是可以满足,但是在大数据量(几万或者几十万)中性能会大大降低
2、准确性:mysql like 模糊查询的正确率不太高
3、搜索成功率:mysql 获取数据后不会进行相关度排序(热门搜索越多 得分越高也越容易查询到,
mysq没有需要自己手动进行处理(加一个相关字段等方式))
使用lucene针对这些大数据量的数据搜索会更快,并且lucene提供了多种形式的查询条件,能根据用户的应用来自定义使用多种方式进行查询。
全文搜索相关知识:https://blog.csdn.net/qq_18860653/article/details/78975556
java中的搜索引擎框架:https://blog.csdn.net/xinghuo0007/article/details/53692871
三、lucene技术概览
3.1、lucene的架构图
3.2、lucene的相关模块
分析模块 org.apache.lucene.analysis | 分词器定义、标准分词器的实现 各种各样的分词器实现 |
编解码模块org.apache.lucene.codes | 编解码模块 |
文档模块org.apache.lucene.document | 文档相关 进行存储文档内容需要进行封装成的相关对象 |
索引相关模块 org.apache.lucene.index | 索引相关 对文档模块中的对象进行创建索引的过程,主要由IndexWriter进行实现 |
搜索模块 org.apache.lucene.search | lucene中提供了多种查询对象实现类 QueryParser(查询条件),主要由IndexSearcher 对象进行查询操作 |
存储模块org.apache.lucene.store | 存储相关 索引的读写 |
Lucene的similarity模块 | 相关度排序以及打分操作 Lucene的similarity模块主要负责对相关性打分的实现 |
3.3、lucene的术语,常用对象
IndexWriter |
lucene中最重要的的类之一,它主要是用来将文档加入索引,同时控制索引过程中的一些参数使用 |
Analyzer |
分析器,主要用于分析搜索引擎遇到的各种文本。常用的有StandardAnalyzer分析器,StopAnalyzer分析器,WhitespaceAnalyzer分析器等。 |
Directory |
索引存放的位置;lucene提供了两种索引存放的位置,一种是磁盘,一种是内存。一般情况将索引放在磁盘上;相应地lucene提供了FSDirectory和RAMDirectory两个类。 |
Document |
Document相当于一个要进行索引的单元,任何可以想要被索引的文件都必须转化为Document对象才能进行索引。代表一个虚拟文档与字段,其中字段是可包含在物理文档的内容,元数据等对象。包含Field字段,参阅Field域 |
Hits |
在搜索完成之后,需要把搜索结果返回并显示给用户,只有这样才算是完成搜索的目的。 在Lucene中,搜索的结果的集合是用Hits类的实例来表示的。 |
IndexSearcher | 是lucene中最基本的检索工具,所有的检索都会用到IndexSearcher工具 |
Query |
查询,lucene中支持模糊查询,语义查询,短语查询,组合查询等等 |
QueryParser | 是一个解析用户输入的工具,可以通过扫描用户输入的字符串,生成Query对象 |
Index-索引库 |
Document的集合组成索引; 和一般的数据库不一样,Lucene不支持定义主键,在Lucene中不存在一个叫做Index的类,通过IndexWriter来写索引,通过IndexReader来读索引; 索引库在物理形式上一般是位于一个路径下的一系列文件; |
Analyzer-分析器 |
一段有意义的文字需要通过Analyzer分析器分割成一个个词语后才能按关键字搜索; StandardAnalyzer是Lucene中最常用的分析器,不同的语言可以使用不同的搜索器; |
Token-词 |
Analyzer返回的结果是一串Token; Token包含一个代表词本身含义的字符串和该词在文章中相应的起止偏移位置,Token还包含一个用来存储词类型的字符串; |
Document-文档 |
一个Document代表索引库中的一条记录,由很多的Field组成;Index和Search的最小单位(要搜索的信息封装成Document后通过IndexWriter写入索引库,调用Searcher接口按关键词搜索后,返回的也是一个封装后的Document列表); |
Field-文档列 |
一个Document可以包含多个列,由很多的Term组成,包括Field Name和Field Value; 与一般数据库不同,一个文档的一个列可以有多个值 |
Term-词语 |
是搜索语法的最小单位(复杂的搜索语法会分解成一个Term查询); Term由很多的字节组成,一般将Text类型的Field Value分词之后的每个最小单元叫做Term; |
四、lucene的相关模块详解
4.1、Analyzer (分析模块)
其中主要包含Tokenizer分词器和TokenFilter过滤器两部分,相关的实现SimpleAnalyzer,StopAnalyzer等,
Tokenizer分词器主要负责对文本内容进行切分形成最小的进入索引的最小单元。TokenFilter过滤器对Tokenizer切分出来的内容进行预处理(过滤处理 单复数转换,错误单词更正等)
4.2、Directory 索引文件存放路径
Directory常用的两个子类 FSDirectory 文件系统目录,索引文件存放在文件中,RAMDirectory类,索引文件存放在内存中。
前者存储的索引文件可以比较大,后者获取索引的速度快。
4.3、Query对象
Query是查询对象的抽象类,IndexSearcher 进行查询使用该对象,该对象可以进行创建,也可以使用QueryParser来将语句转换为Query对象
4.4、Hits对象
五、lucene的Demo
5.1、建立索引
//创建索引
@Test
public void testIndex(){
try {
//lucene索引的存放路径 这里选择使用文件系统来进行存放,当前项目的index目录下
Directory directory = FSDirectory.open(Paths.get("index"));
//中文分词器
Analyzer analyzer = new IKAnalyzer();
//使用lucene的标准分词器
//Analyzer analyzer = new StandardAnalyzer();
IndexWriterConfig config = new IndexWriterConfig(analyzer);
//核心对象进行相关创建索引的操作
IndexWriter writer = new IndexWriter(directory,config);
writer.deleteAll();
//文本对象 lucene中创建创建索引以及根据索引查询出来的均为Document
Document document = new Document();
/**
* StringField 不进行分词,只进行索引
* https://blog.csdn.net/havebeenstand/article/details/80557540
*/
document.add(new TextField("name","XXX,我是一个程序员", Field.Store.YES));
Document document2 = new Document();
document2.add(new TextField("name","XXX,我是一个北飘的蚁族", Field.Store.YES));
Document document3 = new Document();
document3.add(new TextField("name","XXX,我是无奈的程序员", Field.Store.YES));
writer.addDocument(document);
writer.addDocument(document2);
writer.addDocument(document3);
//关闭索引操作
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
5.2、搜索操作
//搜索操作
@Test
public void testSearcher(){
try {
//lucene索引的存放路径
Directory directory = FSDirectory.open(Paths.get("index"));
//获取索引目录的Reader
IndexReader reader = DirectoryReader.open(directory);
//执行搜索操作的核心对象
IndexSearcher searcher = new IndexSearcher(reader);
//分词器
//Analyzer analyzer = new StandardAnalyzer();
Analyzer analyzer = new IKAnalyzer();
//查询对象的解析类,将搜索的关键字符串解析程Query对象进行查询
QueryParser queryParser = new QueryParser("name",analyzer);
Query query = queryParser.parse("程序员");
//执行相关的查询操作 第一个参数 查询对象 第二个参数需要查询的总记录
TopDocs topDocs = searcher.search(query,1);
log.info("查询的命中总记录数:{}",topDocs.totalHits);
log.info("查询的得分:{}",topDocs.getMaxScore());
for(ScoreDoc scoreDoc : topDocs.scoreDocs){
Document document = searcher.doc(scoreDoc.doc);
log.info("程序中的name: {}",document.get("name"));
}
} catch (IOException e) {
e.printStackTrace();
} catch (ParseException e) {
e.printStackTrace();
}
}
5.3、luke的使用
luke是lucene的第三方工具包,可以查看我们创建的索引是否正确,以及查询的测试。方便我们调试程序相关的错误。