Lucene官方网站:http://lucene.apache.org/
下载解压后得到一个Lucene完整的开发工具包
Lucene版本:lucene-7.4.0
Jdk要求:1.8以上
该案例是把本地文件夹中的文件创建索引,然后再查询。
方式一:StandardAnalyzer 英文分析器
使用Lucene自带的默认标准分析器: StandardAnalyzer,该分析器只使用于纯英文文本。
a、 创建java工程,导入jar包
lucene-core-7.4.0.jar
lucene-analyzers-common-7.4.0.jar
commons-io-2.6.jar
b、创建索引库
/**
* 创建索引库
*/
@Test
public void createIndexLibrary() throws Exception {
//1、创建一个directory对象,指定存放索引的位置
Directory directory = FSDirectory.open(new File("F:\\IndexLibrery").toPath());
//2、创建一个IndexWriter对象。如果IndexWriterConfig不传参,则默认使用StandardAnalyzer标准分析器
IndexWriter indexWriter = new IndexWriter(directory,new IndexWriterConfig());
//3、读取磁盘上的文件目录,并为每一个文件创建一个文档对象
File dir = new File("F:\\searchsource");
File[] files = dir.listFiles();
for (File file : files) {
//获取文件名
String fileName = file.getName();
//获取文件路径
String filePath = file.getPath();
//获取文件内容
String fileContent = FileUtils.readFileToString(file, "utf-8");
//获取文件大小
long fileSize = FileUtils.sizeOf(file);
//创建文本域Filed,(参数:域的名称、域的内容,是否存储)
Field fieldName =new TextField("name",fileName, Field.Store.YES);
//Field fieldPath =new TextField("path",filePath, Field.Store.YES);
Field fieldPath = new StoredField("path", filePath); //该域对象只用于存储,不分析,不索引
Field fieldContent =new TextField("content",fileContent, Field.Store.YES);
//Field fieldSize =new TextField("size",fileSize+"", Field.Store.YES);
LongPoint fileSizeValue = new LongPoint("size", fileSize); //该域对象只用于计算
Field fieldSize = new StoredField("size", fileSize); //该域对象只用于存储,不分析,不索引
//4、向文本对象中添加域
Document document = new Document();
document.add(fieldName);
document.add(fieldPath);
document.add(fieldContent);
document.add(fileSizeValue);
document.add(fieldSize);
//5、把文本对象添加到索引库
indexWriter.addDocument(document);
}
//6、关闭IndexWriter对象
indexWriter.close();
}
c、查询索引库
/**
* 查询索引库,查询关键字 “spring”
*/
@Test
public void queryIndexLibrery() throws Exception {
//1、创建一个directory对象,指定索引库的位置
Directory directory = FSDirectory.open(new File("F:\\IndexLibrery").toPath());
//2、创建一个IndexReader对象
IndexReader indexReader = DirectoryReader.open(directory);
//3、创建一个IndexSearcher对象,传入IndexReader对象
IndexSearcher indexSearcher = new IndexSearcher(indexReader);
//4、创建一个Query对象,(参数:域的名称,查询的关键字)
Query query = new TermQuery(new Term("content","spring"));
//5、执行查询(参数:query对象,显示的记录数)
TopDocs topDocs = indexSearcher.search(query, 10);
//6、获取查询的总记录数
System.out.println("查询的总记录数为:"+topDocs.totalHits);
//7、取文档列表,操作
ScoreDoc[] docs = topDocs.scoreDocs;
for (ScoreDoc doc : docs) {
//获取文档id
int docId = doc.doc;
//根据文档id获取
Document document = indexSearcher.doc(docId);
//通过文本域名称获取内容
System.out.println("文件名:"+document.get("name"));
System.out.println("文件路径:"+document.get("path"));
//System.out.println("文件内容:"+document.get("content"));
System.out.println("文件大小:"+document.get("size"));
System.out.println("-------------分割线---------------");
}
//8、关闭indexReader对象
indexReader.close();
}
方式二:IKAnalyzer中文分析器
由于Lucene自带的中文解析器会把中文解析成单独的汉字,而不是词组,这不是我们所想要的。所以,我们引入第三方的中文解析器 IKAnalyzer
注意:
该中文分析器是第三方的,所以需要导额外的jar包,以及 配置文件 、扩展词典 和 停用词词典
a、 创建java工程,导入jar包
lucene-core-7.4.0.jar
lucene-analyzers-common-7.4.0.jar
commons-io-2.6.jar
IK-Analyzer-1.0-SNAPSHOT.jar (中文解析器jar包)
b、 添加IKAnalyzer的配置文件、扩展词典、停用词词典
配置文件:IKAnalyzer.cfg.xml。主要用来配置用户所需要的词典(扩展词典、停用词词典)
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<comment>IK Analyzer 扩展配置</comment>
<!--用户可以在这里配置自己的扩展字典,可以追加 -->
<entry key="ext_dict">hotword.dic;</entry>
<!--用户可以在这里配置自己的扩展停止词字典,可以追加-->
<entry key="ext_stopwords">stopword.dic;</entry>
</properties>
扩展词典:hotword.dic 。是用来记录一些常用词组的文件,一个词组占一行。词组可以按需求来追加
停用词词典:stopword.dic 。是用来记录一些不被解析的词组的文件,比如一些敏感词汇…,一个词组占一行。词组也可以按需求来追加
注意:hotword.dic和stopword.dic文件的格式只能为UTF-8,注意是无BOM 的UTF-8 编码。也就是说禁止使用windows记事本编辑扩展词典文件
c、 创建索引库
/**
* 创建索引库
*/
@Test
public void createIndexLibrary() throws Exception {
//1、创建一个directory对象,指定存放索引的位置
Directory directory = FSDirectory.open(new File("F:\\IndexLibrery").toPath());
//2、创建一个IndexWriter对象。传入中文解析器
Analyzer analyzer = new IKAnalyzer(); //创建中文分析器
IndexWriter indexWriter = new IndexWriter(directory,new IndexWriterConfig(analyzer));
//3、读取磁盘上的文件目录,为每一个文件创建一个文档对象
File dir = new File("F:\\searchsource");
File[] files = dir.listFiles();
for (File file : files) {
//获取文件名
String fileName = file.getName();
//获取文件路径
String filePath = file.getPath();
//获取文件内容
String fileContent = FileUtils.readFileToString(file, "utf-8");
//获取文件大小
long fileSize = FileUtils.sizeOf(file);
//创建文本域Filed,(参数:域的名称、域的内容,是否存储)
Field fieldName =new TextField("name",fileName, Field.Store.YES);
//Field fieldPath =new TextField("path",filePath, Field.Store.YES);
Field fieldPath = new StoredField("path", filePath); //该域对象只用于存储,不分析,不索引
Field fieldContent =new TextField("content",fileContent, Field.Store.YES);
//Field fieldSize =new TextField("size",fileSize+"", Field.Store.YES);
LongPoint fileSizeValue = new LongPoint("size", fileSize); //该域对象只用于计算
Field fieldSize = new StoredField("size", fileSize); //该域对象只用于存储,不分析,不索引
//4、向文本对象中添加域
Document document = new Document();
document.add(fieldName);
document.add(fieldPath);
document.add(fieldContent);
document.add(fileSizeValue);
document.add(fieldSize);
//5、把文本对象添加到索引库
indexWriter.addDocument(document);
}
//6、关闭IndexWriter对象
indexWriter.close();
}
d、 查询索引库
/**
* 查询索引库,查询关键字 “全文”
*/
@Test
public void queryIndexLibrery() throws Exception {
//1、创建一个directory对象,指定索引库的位置
Directory directory = FSDirectory.open(new File("F:\\IndexLibrery").toPath());
//2、创建一个IndexReader对象
IndexReader indexReader = DirectoryReader.open(directory);
//3、创建一个IndexSearcher对象,传入IndexReader对象
IndexSearcher indexSearcher = new IndexSearcher(indexReader);
//4、创建一个Query对象,(参数:域的名称,查询的关键字)
Query query = new TermQuery(new Term("content","全文"));
//5、执行查询(参数:query对象,显示的记录数)
TopDocs topDocs = indexSearcher.search(query, 10);
//6、获取查询的总记录数
System.out.println("查询的总记录数为:"+topDocs.totalHits);
//7、取文档列表,操作
ScoreDoc[] docs = topDocs.scoreDocs;
for (ScoreDoc doc : docs) {
//获取文档id
int docId = doc.doc;
//根据文档id获取
Document document = indexSearcher.doc(docId);
//通过文本域名称获取内容
System.out.println("文件名:"+document.get("name"));
System.out.println("文件路径:"+document.get("path"));
//System.out.println("文件内容:"+document.get("content"));
System.out.println("文件大小:"+document.get("size"));
System.out.println("---------------------------------分割线------------------------------------");
}
//8、关闭indexReader对象
indexReader.close();
}
查询各个分析器执行的效果代码
1、StandardAnalyzer 标准分析器
/**
*
* 查看默认标准分析器 StandardAnalyzer 执行的效果
* 该标准分析器只对【英文】有效,而中文分析后是单独的文字,对中文词语的查询则无效
*/
@Test
public void testAnalyzer() throws Exception{
//1)创建一个Analyzer对象,StandardAnalyzer对象
Analyzer analyzer = new StandardAnalyzer();
//2)使用分析器对象的tokenStream方法获得一个TokenStream对象(参数:域的名称(没有可以为空),内容)
TokenStream tokenStream = analyzer.tokenStream("","sdfgsdeg dsfgdg dsgdg gkjt awetwey rtur,yweywe alajg dgsdjh dsgba.");
//3)向TokenStream对象中设置一个引用,相当于数一个指针
CharTermAttribute charTermAttribute = tokenStream.addAttribute(CharTermAttribute.class);
//4)调用TokenStream对象的rest方法。如果不调用抛异常
tokenStream.reset();
//5)使用while循环遍历TokenStream对象
while(tokenStream.incrementToken()){
System.out.println(charTermAttribute.toString());
}
//6)关闭TokenStream对象
tokenStream.close();
}
执行效果为:
2、IKAnalyzer 中文分析器
/**
*
* 查看中文分析器 IKAnalyzer 执行的效果
* 该标准分析器会把 中文按 常用词文件 中的格式分析出来,把停用词中的词组过滤掉
* 英文词组也会是一个完整的词组
*/
@Test
public void testAnalyzer() throws Exception{
//1)创建一个Analyzer对象,IKAnalyzer对象
Analyzer analyzer = new IKAnalyzer();
//2)使用分析器对象的tokenStream方法获得一个TokenStream对象(参数:域的名称,内容)
TokenStream tokenStream = analyzer.tokenStream("", "2017年12月14日 - Lucene概述公安局Lucene是一款高性能的、可扩展的信息检索(IR)工具库。信息检索是指文档搜索、文档内信息搜索或者文档相关的元数据搜索等操作。");
//3)向TokenStream对象中设置一个引用,相当于数一个指针
CharTermAttribute charTermAttribute = tokenStream.addAttribute(CharTermAttribute.class);
//4)调用TokenStream对象的rest方法。如果不调用抛异常
tokenStream.reset();
//5)使用while循环遍历TokenStream对象
while(tokenStream.incrementToken()){
System.out.println(charTermAttribute.toString());
}
//6)关闭TokenStream对象
tokenStream.close();
}
执行效果为:
“公安局”为一个停用词,已经过滤掉了