Lucene全文检索入门体验

2018-03-01 11:19:46来源:oschina作者:RobertZou人点击

分享

Lucene是Apache开源的全文检索框架, 是单纯的搜索工具, 简单易用. 现在已经出到5.2.1的版本, 只需在项目中导入必需的几个jar包就能使用. 使用的过程可以概括为,


1) 建立索引


2) 搜索查找, 获取搜索结果

这里我们一起先来学习几个会用到的核心类:


Directory


该类在Lucene中用于描述索引存放的位置信息. 比如:

[java]view plaincopy


Directorydir=FSDirectory.open(Paths.get("c://lucene//index"));

其中" c://lucene//index" 是存放索引的文件夹位置.

Analyzer


Analyzer是Lucene的分词器, 可以说是分词解析技术也可以说是搜索引擎的核心技术之一. 一句话被断句分词分析, .使搜索结果更智能更精准. 中文词库分词, 可以使用IKAnalyzer等中文分词工具包.

Analyzer这个类的作用要结合IndexWriterConfig和IndexWriter这两个类去认识:


IndexWriterConfig, 从类名可知, 是一个保存参数配置的类, 用于生成IndexWriter. 比如:

[java]view plaincopy


IndexWriterConfigiwc=newIndexWriterConfig(luceneAnalyzer);
iwc.setOpenMode(OpenMode.CREATE);
IndexWriterindexWriter=newIndexWriter(dir,iwc);

setOpenMode(...) 设置了IndexWriter的打开方式.

当然还有更多的参数设置, 可以参考这篇文章哦.IndexWriterConfig配置参数说明

上面的三行代码也是创建一个IndexWriter的过程. (dir这个参数就是第一个提及的类Directory.)


IndexWriter 是建立索引的核心类. 如果你也知道Android的SharePreference,SharePreference里面有一个Editor类.IndexWriter 就是类似Editor这样的类, 可以针对索引进行添加(创建新的索引并写入索引文档中), 删除(从索引文档删除索引)和更新(更新索引文档中的索引) 操作. 顺便提一下, Lucene的索引, 会生成对应的索引文档, 所以最好建立文件夹专门存放这些文档.

Document


Document类顾名思义是"文件"类, 其实它是用来存放Field集合. 可以理解为存放文件, 一般都是可转换的文本信息, 比如doc, txt等等. 当把用于被查找的文件信息加入Document后, 再通过

[java]view plaincopy


indexWriter.addDocument(document);

这样就添加了一个索引. 来到这里, 也许你会想到, 以后要查询直接先来索引这里就行了.


IndexReader


对应于IndexWriter, 就有IndexReader. 创建方法 :

[java]view plaincopy


IndexReaderreader=DirectoryReader.open(FSDirectory.open(Paths.get(index)));

它只读取索引文档. 然后交给检索工具IndexSearcher 去完成查找. 根据传进Query检索条件进行检索查找后, 会得到一个ScoreDoc类型的结果集, 然后读取它的Document信息, 就能获取检索结果的具体信息, 比如关键字包含在哪些内容中, 已经这些内容文档的存放路径等等. 这样就算是完成整个检索过程了.

OK, 下面我们来简单的例子体验下, 有兴趣可以自己去看文档详细了解哦.


注: 本例子的代码来自网络, 是很简单易懂的例子, 所以就不再另外写了, 这里只是体验学习, 我们直接学习别人的. 额, 原作者不知道是谁了, 在这里感谢一下.


经过上面的关键类的介绍, 相信看下面例子的代码会容易懂很多了, So 直接上代码.


1) 建立索引文档.


随便在本地建立一个文件夹, 比如C盘根目录创建index文件夹. 路径就是 C:/index . 而要检索的内容文档放在 C盘根目录的source文件夹中, 路径就是C:/source .

[java]view plaincopy


publicclassCreateIndex{
publicstaticvoidmain(String[]args)throwsException{
/*指明要索引文件夹的位置,这里是C盘的source文件夹下*/
FilefileDir=newFile("C://source");/*这里放索引文件的位置*/
//FileindexDir=newFile("c://index");
StringindexPath="c://index";//Directorydir=FSDirectory.open(indexDir);//v3.6.0
Directorydir=FSDirectory.open(Paths.get(indexPath));//AnalyzerluceneAnalyzer=newStandardAnalyzer(Version.LUCENE_3_6_0);
AnalyzerluceneAnalyzer=newStandardAnalyzer();
IndexWriterConfigiwc=newIndexWriterConfig(luceneAnalyzer);
iwc.setOpenMode(OpenMode.CREATE);
IndexWriterindexWriter=newIndexWriter(dir,iwc);
File[]textFiles=fileDir.listFiles();
longstartTime=newDate().getTime();//增加document到索引去
for(inti=0;i if(textFiles[i].isFile()
){
System.out.println("File"+textFiles[i].getCanonicalPath()
+"正在被索引....");
Stringtemp=FileReaderAll(textFiles[i].getCanonicalPath(),
"GBK");
System.out.println(temp);
Documentdocument=newDocument();FieldFieldPath=newStringField("path",textFiles[i].getPath(),Field.Store.YES);
FieldFieldBody=newTextField("body",temp,Field.Store.YES);
document.add(FieldPath);
document.add(FieldBody);
indexWriter.addDocument(document);
}
}
indexWriter.close();//测试一下索引的时间
longendTime=newDate().getTime();
System.out
.println("这占用了"
+(endTime-startTime)
+"毫秒来把文档增加到索引里面去!"
+fileDir.getPath());
}publicstaticStringFileReaderAll(StringFileName,Stringcharset)
throwsIOException{
BufferedReaderreader=newBufferedReader(newInputStreamReader(
newFileInputStream(FileName),charset));
Stringline=newString();
Stringtemp=newString();while((line=reader.readLine())!=null){
temp+=line;
}
reader.close();
returntemp;
}}

2) 执行检索查找的类:


[java]view plaincopy


publicclassExecuteQuery{
publicstaticvoidmain(String[]args)throwsIOException,ParseException{
Stringindex="c://index";//搜索的索引路径
//IndexReaderreader=IndexReader.open(FSDirectory.open(Paths.get(index));//v3.6.0的写法
IndexReaderreader=DirectoryReader.open(FSDirectory.open(Paths.get(index)));
IndexSearchersearcher=newIndexSearcher(reader);//检索工具
ScoreDoc[]hits=null;
StringqueryString="好";//搜索的索引名称
Queryquery=null;
Analyzeranalyzer=newStandardAnalyzer();
try{
//QueryParserqp=newQueryParser(Version.LUCENE_3_6_0,"body",analyzer);//用于解析用户输入的工具v3.6.0
QueryParserqp=newQueryParser("body",analyzer);//用于解析用户输入的工具
query=qp.parse(queryString);
}catch(ParseExceptione){
//TODO:handleexception
}
if(searcher!=null){
TopDocsresults=searcher.search(query,10);//只取排名前十的搜索结果
hits=results.scoreDocs;
Documentdocument=null;
for(inti=0;i document=searcher.doc(hits[i].doc);
Stringbody=document.get("body");
Stringpath=document.get("path");
Stringmodifiedtime=document.get("modifiField");
System.out.println("BODY---"+body+"");
System.out.println("PATH--"+path);
}
if(hits.length>0){
System.out.println("输入关键字为:"+queryString+","+"找到"+hits.length+"条结果!");}
//searcher.close();
reader.close();
}
}}

例子里面是搜索"好"字. 效果如图:


然后修改一下内容文档:



搜索"努力"



中文搜索ok~

最新文章

123

最新摄影

闪念基因

微信扫一扫

第七城市微信公众平台