Lucene不是一个完整的全文索引应用,而是是一个用Java写的全文索引引擎工具包,它可以方便的嵌入到各种应用中实现针对应用的全文索引/检索功能。
Lucene的目标是为各种中小型应用程序加入全文检索功能
一、开始
首先在Apache下载Lucene 2.3.0包,其中包含了核心jar和LuceneAPI文档,解压后,将 lucene-core-2.3.0.jar放在classpath中。
首先在Apache下载Lucene 2.3.0包,其中包含了核心jar和LuceneAPI文档,解压后,将 lucene-core-2.3.0.jar放在classpath中。
二、创建索引
创建索引时需要指定存放索引的目录(将来检索时需要对这个目录中的索引进行检索),和文件的目录(如果是对文件进行索引的话)代码如下:
public void crateIndex()
throws Exception {
File indexDir = new File(“D://luceneIndex”);
File indexDir = new File(“D://luceneIndex”);
// 存储索引文件夹
File dataDir =
new File(“D://test”);
// 需要检索文件夹
Analyzer luceneAnalyzer = new PaodingAnalyzer();
//
PaodingAnalyzer这个类是庖丁解牛中文分词分析器类继承了Lucene的Analyzer接口,对于检索中文分词有很大帮助
File[] dataFiles = dataDir.listFiles();
boolean fileIsExist =
false;
if (indexDir.listFiles().length == 0)
fileIsExist =
true;
IndexWriter indexWriter =
new IndexWriter(indexDir, luceneAnalyzer, fileIsExist);
// 第三个参数是一个布尔型的变量,如果为 true 的话就代表创建一个新的索引,为 false 的话就代表在原来索引的基础上进行操作。
long startTime =
new Date().getTime();
this.doIndex(dataFiles, indexWriter);
indexWriter.optimize();//优化索引
indexWriter.close();//关闭索引
long endTime =
new Date().getTime();
System.
out.println(“It takes “ + (endTime – startTime)
+ ” milliseconds to create index for the files in directory “ + dataDir.getPath());
{color:black}}
* private{*}
void doIndex(File[] dataFiles, IndexWriter indexWriter)
throws Exception {
for (
int i = 0; i < dataFiles.length; i++) {
if (dataFiles[i].isFile() && dataFiles[i].getName().endsWith(“.html”)) {//索引所有html格式文件
System.
out.println(“Indexing file “ + dataFiles[i].getCanonicalPath());
Reader txtReader =
new FileReader(dataFiles[i]);
Document document =
new Document();
// Field.Store.YES 存储Field.Store.NO 不存储
// Field.Index.TOKENIZED 分词 Field.Index.UN_TOKENIZED 不分词
document.add(
new Field(“path”, dataFiles[i].getCanonicalPath(), Field.Store.
YES,Field.Index.
UN_TOKENIZED));
document.add(
new Field(“filename”, dataFiles[i].getName(), Field.Store.
YES, Field.Index.
TOKENIZED));
// 另外一个构造函数,接受一个Reader对象
document.add(
new Field(“contents”, txtReader));
indexWriter.addDocument(document);
{color:black}}
else if (dataFiles[i].isFile() && dataFiles[i].getName().endsWith(“.doc”)) {//索引所有word文件
FileInputStream in =
new FileInputStream(dataFiles[i]);//
获得文件流
WordExtractor extractor =
new WordExtractor(in);//
使用POI对word文件进行解析
String str = extractor.getText();//
返回String
Document document =
new Document();//生成Document对象,其中有3个Field,分别是path,filename,contents
document.add(
new Field(“path”, dataFiles[i].getCanonicalPath(), Field.Store.
YES,
Field.Index.
UN_TOKENIZED));
document.add(
new Field(“filename”, dataFiles[i].getName(), Field.Store.
YES, Field.Index.
TOKENIZED));
// 另外一个构造函数,接受一个Reader对象
document.add(
new Field(“contents”, str, Field.Store.
YES,Field.Index.
TOKENIZED,
Field.TermVector. WITH_POSITIONS_OFFSETS));
Field.TermVector. WITH_POSITIONS_OFFSETS));
indexWriter.addDocument(document);
{color:black}}
else {
if (dataFiles[i].isDirectory()) {
doIndex(dataFiles[i].listFiles(), indexWriter);//使用递归,继续索引文件夹
{color:black}}
{color:black}}
{color:black}}
{color:black}}
从上面代码中可以看到对文件(或者说是数据)创建索引是一件很容易的事,首先确定需要索引的文件夹(或者数据库中的数据注:Lucene只接受数据,他不会区分数据的来源,也就是说不管是什么你只要把它转为String格式的数据,Lucene就能创建索引),然后指定创建后索引存放的地方,我们自己对数据处理后创建一个Document对象这里面你可以自己定义放几个Field,并定义Field是否进行分词什么的,这样索引就创建好了.
注:使用庖丁解牛中文分词,需要将”庖丁”中的词典(dic文件夹)放到classpath 中再把 paoding-analyzer.properties文件也放到classpath中 properties文件内容如下:
paoding.imports={color}
ifexists:classpath:paoding-analysis-default.properties;{color}
ifexists:classpath:paoding-analysis-user.properties;{color}
ifexists:classpath:paoding-knives-user.properties
paoding.dic.home=classpath:dic
三、检索
对于创建数据的索引我们已经了解了,下面介绍一下,检索数据, 检索数据的时候我们不用关心原始的数据或者文件,我们只关心lucene生成的索引,
但是要使用当初生成索引时的同一个分析器进行分析索引.
public void searchIndex()
throws Exception {
String contents = ”项目”;//内容的关键字
String filename = ”测试”;//文件名的关键字
File indexDir =
new File(“D:
luceneIndex”);//存放索引的文件夹
luceneIndex”);//存放索引的文件夹
FSDirectory directory = FSDirectory.
getDirectory(indexDir);
Searcher searcher =
new IndexSearcher(directory);
QueryParser parserContents =
new QueryParser(“contents”, luceneAnalyzer);
QueryParser parserFilename =
new QueryParser(“filename”, luceneAnalyzer);
//使用同一个分析器luceneAnalyzer分别生成两个QueryParser对象
Query query1 = parserContents.parse(contents);
Query query2 = parserFilename.parse(filename);
BooleanQuery query =
new BooleanQuery();
query.add(query1, BooleanClause.Occur.
MUST);
query.add(query2, BooleanClause.Occur.
MUST);
SimpleHTMLFormatter formatter =
new SimpleHTMLFormatter(“<span class=\”highlight\”>”,”</span>”);
Highlighter highlighter =
new Highlighter(formatter,
newQueryScorer(query));
highlighter.setTextFragmenter(
newSimpleFragmenter(60));
//Lucene自带的高亮功能,在Lucene发布的bin中的lucene-2.3.0\contrib\highlighter文件夹下 lucene-highlighter-2.3.0.jar 需要导入
Hits hits = searcher.search(query);
for(
int i=0;i<hits.length();i++){
TokenStream tokenStream = luceneAnalyzer.tokenStream(“contents”,
new StringReader(hits.doc
.get(“contents”)));
![](http://10.0.160.188/wiki/images/icons/emoticons/information.gif)
this.pageContext.getOut().println(“<font style=’font-size:13px’><a href=’”+ hits.doc
.get(“path”) +”‘><b>”+ELFuncUtil.
setStyle(hits.doc
.get(“filename”), filename)+”</b></a></font><br>”);
![](http://10.0.160.188/wiki/images/icons/emoticons/information.gif)
![](http://10.0.160.188/wiki/images/icons/emoticons/information.gif)
String str = highlighter.getBestFragment(tokenStream,hits.doc
.get(“contents”) + ”…”);
![](http://10.0.160.188/wiki/images/icons/emoticons/information.gif)
this.pageContext.getOut().println(“<font style=’font-size:12px’>”+str+”</font>”);
this.pageContext.getOut().println(“<br><hr><br>”);
{color:black}}
{color:black}}
<style>
.highlight {
background: yellow;
color: #CC0033;
{color:black}}
</style>
这样外界的访问直接通过Lucene去检索索引,不去触及真正的文件,效率大大提高.页面再加上一点修饰一个使用Lucene构建的搜索引擎就完成了.