Lucene 是一个基于 Java 的全文信息检索工具包,它不是一个完整的搜索应用程序,而是为你的应用程序提供索引和搜索功能。Lucene 目前是 Apache Jakarta 家族中的一个开源项目。也是目前最为流行的基于 Java 开源全文检索工具包。
目前已经有很多应用程序的搜索功能是基于 Lucene 的,比如 Eclipse 的帮助系统的搜索功能。Lucene 能够为文本类型的数据建立索引,所以你只要能把你要索引的数据格式转化的文本的,Lucene 就能对你的文档进行索引和搜索。比如你要对一些 HTML 文档,PDF 文档进行索引的话你就首先需要把 HTML 文档和 PDF 文档转化成文本格式的,然后将转化后的内容交给 Lucene 进行索引,然后把创建好的索引文件保存到磁盘或者内存中,最后根据用户输入的查询条件在索引文件上进行查询。不指定要索引的文档的格式也使 Lucene 能够几乎适用于所有的搜索应用程序。
索引是现代搜索引擎的核心,建立索引的过程就是把源数据处理成非常方便查询的索引文件的过程。为什么索引这么重要呢,试想你现在要在大量的文档中搜索含有某个关键词的文档,那么如果不建立索引的话你就需要把这些文档顺序的读入内存,然后检查这个文章中是不是含有要查找的关键词,这样的话就会耗费非常多的时间,想想搜索引擎可是在毫秒级的时间内查找出要搜索的结果的。这就是由于建立了索引的原因,你可以把索引想象成这样一种数据结构,他能够使你快速的随机访问存储在索引中的关键词,进而找到该关键词所关联的文档。Lucene 采用的是一种称为反向索引(inverted index)的机制。反向索引就是说我们维护了一个词/短语表,对于这个表中的每个词/短语,都有一个链表描述了有哪些文档包含了这个词/短语。这样在用户输入查询条件的时候,就能非常快的得到搜索结果。我们将在本系列文章的第二部分详细介绍 Lucene 的索引机制,由于 Lucene 提供了简单易用的 API,所以即使读者刚开始对全文本进行索引的机制并不太了解,也可以非常容易的使用 Lucene 对你的文档实现索引。
对文档建立好索引后,就可以在这些索引上面进行搜索了。搜索引擎首先会对搜索的关键词进行解析,然后再在建立好的索引上面进行查找,最终返回和用户输入的关键词相关联的文档。
创建索引:
package org.apache.lucene;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;
/**
* 创建索引
*
* @author zxf_noimp
*
*/
public class TxtFileIndexer {
/**
* 创建索引文件
* @param dataFile 文本文件存放的目录
* @param indexFile 生成的索引文件存放的目录
* @throws Exception
*/
public void fileIndexer(String dataFile,String indexFile) throws Exception{
File indexDir = new File(indexFile);
File dataDir = new File(dataFile);
File[] dataFiles = dataDir.listFiles();
IndexWriter indexWriter = new IndexWriter(FSDirectory.open(indexDir), new StandardAnalyzer(Version.LUCENE_CURRENT), true, IndexWriter.MaxFieldLength.LIMITED);
for(int i = 0; i < dataFiles.length; i++){
if(dataFiles[i].isFile() && dataFiles[i].getName().endsWith(".txt")){
System.out.println("Indexing file " + dataFiles[i].getCanonicalPath());
Document document = new Document();
document.add(new Field("path",dataFiles[i].getCanonicalPath(), Field.Store.YES, Field.Index.NOT_ANALYZED));
document.add(new Field("filename",dataFiles[i].getName(), Field.Store.YES, Field.Index.NOT_ANALYZED));
document.add(new Field("content",TxtFileIndexer.loadFileToString(dataFiles[i]),Field.Store.YES, Field.Index.ANALYZED)); //ANALYZED
indexWriter.addDocument(document);
}
}
indexWriter.optimize();
indexWriter.close();
}
/**
* 读取文件内容
* @param file 文件对象
* @return
*/
private static String loadFileToString(File file) {
BufferedReader br = null;
try {
// 字符缓冲流,是个装饰流,提高文件读取速度
br = new BufferedReader(new FileReader(file));
StringBuffer sb = new StringBuffer();
String line = br.readLine();
while (null != line) {
sb.append(line);
line = br.readLine();
//System.out.println(line);
}
return sb.toString();
} catch (FileNotFoundException e) {
System.out.println("文件不存在!");
return null;
} catch (IOException e) {
e.printStackTrace();
return null;
} finally {
try {
br.close();
} catch (IOException e) {
System.out.println("关闭流出现异常");
e.printStackTrace();
}
}
}
public static void main(String[] args) throws Exception {
TxtFileIndexer indexer = new TxtFileIndexer();
indexer.fileIndexer("G:\\luceneData", "G:\\luceneIndex");
}
}
对索引进行检索
package org.apache.lucene;
import java.io.File;
import java.io.IOException;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.store.FSDirectory;
/**
* 对索引进行搜索
*
* @author zxf_noimp
*
*/
public class TxtFileSearcher {
public void fileSearcher(String queryStr,String indexPath) throws IOException {
// 生成的索引文件存放的位置
File indexDir = new File(indexPath);
FSDirectory directory = FSDirectory.open(indexDir);
// 对目录下的索引文件进行搜索
IndexSearcher searcher = new IndexSearcher(directory);
if (!indexDir.exists()) {
System.out.println("The Lucene index is not exist");
return;
}
// 构造了一个Term对象,通过这个Term对象,我们指定了要在文档的内容中搜索包含关键词"我"的文档
Term term = new Term("content", queryStr.toLowerCase());
// 利用这个Term对象构造出TermQuery对象并把这个TermQuery对象传入到IndexSearcher的search方法中进行查询
TermQuery luceneQuery = new TermQuery(term);
TopDocs ts = searcher.search(luceneQuery, 100); // 老版本中 Hits hits = searcher.search(luceneQuery);
System.out.println("数量:" + ts.totalHits);
ScoreDoc[] hits = ts.scoreDocs;
for (int i = 0; i < hits.length; i++) {
Document document = searcher.doc(hits[i].doc);
System.out.println("FilePath: " + document.get("path"));
System.out.println("FileContent:"+ document.getField("content").stringValue());
System.out.println("FileName:"+ document.getField("filename").stringValue());
}
}
public static void main(String[] args) throws Exception {
TxtFileSearcher searcher = new TxtFileSearcher();
searcher.fileSearcher("我", "G:\\luceneIndex");
}
}
http://www.ibm.com/developerworks/cn/java/j-lo-lucene1/
http://www.ibm.com/developerworks/cn/web/wa-lucene2/
http://www.iteye.com/wiki/Lucene/1527-%E6%AD%A3%E5%9C%A8%E7%BF%BB%E8%AF%91%E4%B8%AD...
http://chinaxxren.iteye.com/blog/548505
http://www.chedong.com/tech/lucene.html
http://www.lucene.com.cn/about.htm#_Toc43005315