Lucene 安装和应用实战

JAVA herman 790浏览 0评论
公告:“业余草”微信公众号提供免费CSDN下载服务(只下Java资源),关注业余草微信公众号,添加作者微信:xttblog,发送下载链接帮助你免费下载!
本博客日IP超过1800,PV 2600 左右,急需赞助商。
极客时间所有课程通过我的二维码购买后返现24元微信红包,请加博主新的微信号:xttblog,之前的微信号好友位已满,备注:返现
所有面试题(java、前端、数据库、springboot等)一网打尽,请关注文末小程序
视频教程免费领

这篇文章我们将进入 Lucene 的实战阶段,我们将通过 Lucene 的一个简单入门程序,来实现它对全文检索,高效的搜索应用。

下载

http://jakarta.apache.org/lucene/

Lucene中的一些比较复杂的词法分析是用JavaCC生成的(JavaCC:JavaCompilerCompiler,纯Java的词法分析生成器),所以如果从源代码编译或需要修改其中的QueryParser、定制自己的词法分析器,还需要从https://javacc.dev.java.net/下载javacc。

lucene的组成结构

对于外部应用来说索引模块(index)和检索模块(search)是主要的外部应用入口。

org.apache.Lucene.search/ 搜索入口
org.apache.Lucene.index/ 索引入口
org.apache.Lucene.analysis/ 语言分析器
org.apache.Lucene.queryParser/ 查询分析器
org.apache.Lucene.document/ 存储结构
org.apache.Lucene.store/  底层IO/存储结构
org.apache.Lucene.util/ 一些公用的数据结构

索引过程

从命令行读取文件名(多个),将文件分路径(path字段)和内容(body字段)2个字段进行存储,并对内容进行全文索引。索引的单位是Document对象,每个Document对象包含多个字段Field对象,针对不同的字段属性和数据输出的需求,对字段还可以选择不同的索引/存储字段规则,列表如下:

方法 切词 索引 存储 用途
Field.Text(String name, String value) Yes Yes Yes 切分词索引并存储,比如:标题,内容字段
Field.Text(String name, Reader value) Yes Yes No 切分词索引不存储,比如:META信息,
不用于返回显示,但需要进行检索内容
Field.Keyword(String name, String value) No Yes Yes 不切分索引并存储,比如:日期字段
Field.UnIndexed(String name, String value) No No Yes 不索引,只存储,比如:文件路径
Field.UnStored(String name, String value) Yes Yes No 只全文索引,不存储

看下面的一个简单的 Lucene 搜索程序:

public class IndexFiles { 
  //使用方法:: IndexFiles [索引输出目录] [索引的文件列表] ... 
	public static void main(String[] args) throws Exception {
		String indexPath = args[0];
		IndexWriter writer;
		//用指定的语言分析器构造一个新的写索引器(第3个参数表示是否为追加索引)
		writer = new IndexWriter(indexPath, new SimpleAnalyzer(), false);
		for (int i=1; i<args.length; i++) {
			System.out.println("Indexing file " + args[i]);
			InputStream is = new FileInputStream(args[i]);
			//构造包含2个字段Field的Document对象
			//一个是路径path字段,不索引,只存储
			//一个是内容body字段,进行全文索引,并存储
			Document doc = new Document();
			doc.add(Field.UnIndexed("path", args[i]));
			doc.add(Field.Text("body", (Reader) new InputStreamReader(is)));
			//将文档写入索引
			writer.addDocument(doc);
			is.close();
		};
		//关闭写索引器
		writer.close();
	}
}

上面是一个创建索引的过程,索引过程中可以看到:

  • 语言分析器提供了抽象的接口,因此语言分析(Analyser)是可以定制的,虽然lucene缺省提供了2个比较通用的分析器SimpleAnalyser和StandardAnalyser,这2个分析器缺省都不支持中文,所以要加入对中文语言的切分规则,需要修改这2个分析器。
  • Lucene并没有规定数据源的格式,而只提供了一个通用的结构(Document对象)来接受索引的输入,因此输入的数据源可以是:数据库,WORD文档,PDF文档,HTML文档……只要能够设计相应的解析转换器将数据源构造成成Docuement对象即可进行索引。
  • 对于大批量的数据索引,还可以通过调整IndexerWrite的文件合并频率属性(mergeFactor)来提高批量索引的效率。

检索过程

搜索结果返回的是Hits对象,可以通过它再访问Document==>Field中的内容。

假设根据body字段进行全文检索,可以将查询结果的path字段和相应查询的匹配度(score)打印出来。看下面的一个搜索案例:

public class Search { 
	public static void main(String[] args) throws Exception {
		String indexPath = args[0], queryString = args[1];
		//指向索引目录的搜索器
		Searcher searcher = new IndexSearcher(indexPath);
		//查询解析器:使用和索引同样的语言分析器
		Query query = QueryParser.parse(queryString, "body", 
								  new SimpleAnalyzer());
		//搜索结果使用Hits存储
		Hits hits = searcher.search(query);
		//通过hits可以访问到相应字段的数据和查询的匹配度
		for (int i=0; i<hits.length(); i++) {
		  System.out.println(hits.doc(i).get("path") + "; Score: " + 
							 hits.score(i));
		};
	}
}

在整个检索过程中,语言分析器,查询分析器,甚至搜索器(Searcher)都是提供了抽象的接口,可以根据需要进行定制。

上面简单的百把行代码,就实现了一个 Lucene 检索应用。但是实际使用过程中,还有很多的需求和功能,例如:对内容修改了呢?还有对搜索结果的排序,人工排序,权重干扰,索引优化,分布式等。后面我们继续深入学习!

业余草公众号

最后,欢迎关注我的个人微信公众号:业余草(yyucao)!可加QQ1群:135430763(2000人群已满),QQ2群:454796847(已满),QQ3群:187424846(已满)。QQ群进群密码:xttblog,想加微信群的朋友,之前的微信号好友已满,请加博主新的微信号:xttblog,备注:“xttblog”,添加博主微信拉你进群。备注错误不会同意好友申请。再次感谢您的关注!后续有精彩内容会第一时间发给您!原创文章投稿请发送至532009913@qq.com邮箱。商务合作可添加助理微信进行沟通!

本文原文出处:业余草: » Lucene 安装和应用实战