Lucene是apache软件基金会4 jakarta项目组的一个子项目,是一个开放源代码的全文检索引擎工具包,但它不是一个完整的全文检索引擎,而是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎,部分文本分析引擎(英文与德文两种西方语言)。Lucene的目的是为软件开发人员提供一个简单易用的工具包,以方便的在目标系统中实现全文检索的功能,或者是以此为基础建立起完整的全文检索引擎。Lucene是一套用于全文检索和搜寻的开源程式库,由Apache软件基金会支持和提供。Lucene提供了一个简单却强大的应用程式接口,能够做全文索引和搜寻。在Java开发环境里Lucene是一个成熟的免费开源工具。就其本身而言,Lucene是当前以及最近几年最受欢迎的免费Java信息检索程序库。人们经常提到信息检索程序库,虽然与搜索引擎有关,但不应该将信息检索程序库与搜索引擎相混淆(来自百度百科)
点击查看百度百科:https://baike.baidu.com/item/Lucene
优快云一篇文章介绍:https://blog.youkuaiyun.com/regan_hoo/article/details/78802897
关于Lucene具体介绍不多说,这里写一个应用场景来学会使用Lucene:
我在一个文件夹里面存了一堆txt文本,大小不一,名字不同,里面的内容不同,我要做一个功能实现:
比如我输入一个java,只要名字,路径,内容等等出现了java这个词汇,就返回结果给我
1.建一个java工程,导包(开发中通常是使用老版本的):
2.一步一步来:
我在D盘666文件夹放入一堆文本文件
然后在D盘的temp的index下创建索引库
创建索引:
package lucene; import java.io.File; import org.apache.commons.io.FileUtils; import org.apache.lucene.analysis.Analyzer; import org.apache.lucene.analysis.standard.StandardAnalyzer; import org.apache.lucene.document.Document; import org.apache.lucene.document.Field; import org.apache.lucene.document.TextField; import org.apache.lucene.document.Field.Store; import org.apache.lucene.document.LongField; import org.apache.lucene.document.StoredField; import org.apache.lucene.index.IndexWriter; import org.apache.lucene.index.IndexWriterConfig; import org.apache.lucene.store.Directory; import org.apache.lucene.store.FSDirectory; import org.apache.lucene.util.Version; import org.junit.Test; public class MyFirstLucene { // 创建索引 @Test public void testIndex() throws Exception { // 新建一个索引库(我放在D盘某文件夹内) Directory directory = FSDirectory.open(new File("D:\\temp\\index")); // 新建分析器对象 Analyzer analyzer = new StandardAnalyzer(); // 新建配置对象 IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE_4_10_3, analyzer); // 创建一个IndexWriter对象(参数一个索引库,一个配置) IndexWriter indexWriter = new IndexWriter(directory, config); // 创建域对象 File f = new File("D:\\666"); File[] list = f.listFiles(); for (File file : list) { // 创建一个文档对象 Document document = new Document(); // 文件名称 String file_name = file.getName(); Field fileNameField = new TextField("fileName", file_name, Store.YES); // 文件大小 long file_size = FileUtils.sizeOf(file); Field fileSizeField = new LongField("fileSize", file_size, Store.YES); // 文件路径 String file_path = file.getPath(); Field filePathField = new StoredField("filePath", file_path); // 文件内容 String file_content = FileUtils.readFileToString(file); Field fileContentField = new TextField("fileContent", file_content, Store.YES); // 添加到document document.add(fileNameField); document.add(fileSizeField); document.add(filePathField); document.add(fileContentField); // 创建索引 indexWriter.addDocument(document); } // 关闭资源 indexWriter.close(); } }
好的,运行成功,我打开D盘的temp文件夹中的Index文件夹:存入了一堆看不懂的东西,这就代表创建索引库成功:
3.查询索引:
// 搜索索引 @Test public void testSearch() throws Exception { // 第一步:创建一个Directory对象,也就是索引库存放的位置。 Directory directory = FSDirectory.open(new File("D:\\temp\\index")); // 第二步:创建一个indexReader对象,需要指定Directory对象。 IndexReader indexReader = DirectoryReader.open(directory); // 第三步:创建一个indexSearcher对象,需要指定IndexReader对象 IndexSearcher indexSearcher = new IndexSearcher(indexReader); // 第四步:创建一个TermQuery对象,指定查询的域和查询的关键词。 Query query = new TermQuery(new Term("fileName", "spring")); // 第五步:执行查询(显示条数) TopDocs topDocs = indexSearcher.search(query, 10); // 第六步:返回查询结果。遍历查询结果并输出。 ScoreDoc[] scoreDocs = topDocs.scoreDocs; for (ScoreDoc scoreDoc : scoreDocs) { int doc = scoreDoc.doc; Document document = indexSearcher.doc(doc); // 文件名称 String fileName = document.get("fileName"); System.out.println(fileName); // 文件内容 String fileContent = document.get("fileContent"); System.out.println(fileContent); // 文件大小 String fileSize = document.get("fileSize"); System.out.println(fileSize); // 文件路径 String filePath = document.get("filePath"); System.out.println(filePath); System.out.println("------------"); } // 第七步:关闭IndexReader对象 indexReader.close(); }
实现了基础功能
但是,这里有很大的一个问题:
无法处理中文
4.所以,接下来就处理中文问题:中文分析器(上边的示例采用的是标准分析器,即处理英文的分析器)
首先,我们看看用标准分析器分析中文的结果:
// 查看分析器的分词效果 @Test public void testTokenStream() throws Exception { // 创建一个分析器对象 Analyzer analyzer = new StandardAnalyzer();// 获得tokenStream对象 // 第一个参数:域名,可以随便给一个 // 第二个参数:要分析的文本内容 TokenStream tokenStream = analyzer.tokenStream("test", "高富帅可以用二维表结构来逻辑表达实现的数据"); // 添加一个引用,可以获得每个关键词 CharTermAttribute charTermAttribute = tokenStream.addAttribute(CharTermAttribute.class); // 添加一个偏移量的引用,记录了关键词的开始位置以及结束位置 OffsetAttribute offsetAttribute = tokenStream.addAttribute(OffsetAttribute.class); // 将指针调整到列表的头部 tokenStream.reset(); // 遍历关键词列表,通过incrementToken方法判断列表是否结束 while (tokenStream.incrementToken()) { // 关键词的起始位置 System.out.println("start->" + offsetAttribute.startOffset()); // 取关键词 System.out.println(charTermAttribute); // 结束位置 System.out.println("end->" + offsetAttribute.endOffset()); } tokenStream.close(); }
结果:
这里截取了一部分,发现如果采用了标准分析器,每一个中文都分隔开了,显然有问题
于是不能采用标准分析器:
用一个SmartChinese分析器:
// 查看分析器的分词效果 @Test public void testTokenStream() throws Exception { Analyzer analyzer = new SmartChineseAnalyzer(); TokenStream tokenStream = analyzer.tokenStream("test", "高富帅可以用二维表结构来逻辑表达实现的数据"); CharTermAttribute charTermAttribute = tokenStream.addAttribute(CharTermAttribute.class); OffsetAttribute offsetAttribute = tokenStream.addAttribute(OffsetAttribute.class); tokenStream.reset(); while (tokenStream.incrementToken()) { System.out.println("start->" + offsetAttribute.startOffset()); System.out.println(charTermAttribute); System.out.println("end->" + offsetAttribute.endOffset()); } tokenStream.close(); }
效果有提升:
不过有一个问题:对于新词汇如高富帅这样的,它不识别
如果追求更好的效果:可以采用其他的第三方分析器
比如我这里采用一个IK分析器,可以自己添加进去“高富帅”这种词汇
@Test public void testTokenStream() throws Exception { Analyzer analyzer = new IKAnalyzer(); TokenStream tokenStream = analyzer.tokenStream("test", "高富帅可以用二维表结构来逻辑表达实现的数据"); CharTermAttribute charTermAttribute = tokenStream.addAttribute(CharTermAttribute.class); OffsetAttribute offsetAttribute = tokenStream.addAttribute(OffsetAttribute.class); tokenStream.reset(); while (tokenStream.incrementToken()) { System.out.println("start->" + offsetAttribute.startOffset()); System.out.println(charTermAttribute); System.out.println("end->" + offsetAttribute.endOffset()); } tokenStream.close(); }
添加配置文件
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">ext.dic;</entry> <!--用户可以在这里配置自己的扩展停止词字典--> <entry key="ext_stopwords">stopword.dic;</entry> </properties>
ext.doc:
高富帅
二维表
stopword.dic:

这时候效果:
解决了中文问题,并且可以扩展
上边对于索引库操作只有添加,我们还可以对索引库做其他操作:
查询的时候也可以有多种方式,下面代码示例: