一、Lucene简介
Lucene 是一个基于 Java 的全文信息检索工具包,它不是一个完整的搜索应用程序,而是为你的应用程序提供索引和搜索功能。Lucene 目前是 Apache Jakarta 家族中的一个开源项目。也是目前最为流行的基于 Java 开源全文检索工具包。
目前已经有很多应用程序的搜索功能是基于 Lucene 的,比如 Eclipse 的帮助系统的搜索功能。Lucene 能够为文本类型的数据建立索引,所以你只要能把你要索引的数据格式转化的文本的,Lucene 就能对你的文档进行索引和搜索。比如你要对一些 HTML 文档,PDF 文档进行索引的话你就首先需要把 HTML 文档和 PDF 文档转化成文本格式的,然后将转化后的内容交给 Lucene 进行索引,然后把创建好的索引文件保存到磁盘或者内存中,最后根据用户输入的查询条件在索引文件上进行查询。不指定要索引的文档的格式也使 Lucene 能够几乎适用于所有的搜索应用程序。
二、代码实现
package com.demo.index;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.nio.file.FileSystems;
import java.util.logging.Logger;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field.Store;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.*;
import org.apache.lucene.index.IndexWriterConfig.OpenMode;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.*;
import org.apache.lucene.store.*;
public class LuceneIndex {
private static Logger logger = Logger.getLogger(LuceneIndex.class.getName());
//IndexWriter 索引文件的segment进行写、合并、优化
IndexWriter indexWriter;
//将要存储索引的目录
Directory dir;
public LuceneIndex(){
try{
IndexWriterConfig config = new IndexWriterConfig(new StandardAnalyzer());
config.setOpenMode(OpenMode.CREATE_OR_APPEND);
this.dir = new RAMDirectory();
this.indexWriter = new IndexWriter(dir,config);
}catch (Exception e){
e.printStackTrace();
}
}
//索引保存于内存中
public LuceneIndex(String dataUrl){
try{
IndexWriterConfig config = new IndexWriterConfig(new StandardAnalyzer());
config.setOpenMode(OpenMode.CREATE_OR_APPEND);
this.dir = new RAMDirectory();
this.indexWriter = new IndexWriter(this.dir,config);
//根据传入的URL添加索引
addDocument(dataUrl);
closeWriter();
}catch (Exception e){
e.printStackTrace();
}
}
//索引保存于指定目录
public LuceneIndex(String IndexUrl,String dataUrl){
try{
IndexWriterConfig config = new IndexWriterConfig(new StandardAnalyzer());
config.setOpenMode(OpenMode.CREATE_OR_APPEND);
this.dir = FSDirectory.open(FileSystems.getDefault().getPath(IndexUrl));
this.indexWriter = new IndexWriter(dir,config);
//根据传入的URL添加索引
addDocument(dataUrl);
closeWriter();
}catch (Exception e){
e.printStackTrace();
}
}
public void closeWriter(){
try {
this.indexWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 根据提供的URL添加索引,可是文档或者目录
* @param url 文件或者目录
*/
public void addDocument(String url){
try{
File file = new File(url);
if(file.exists()){
if(file.isFile()){
Document document = getDocument(file);
this.indexWriter.addDocument(document);
}else if(file.isDirectory()){
//File[] dataFiles = new File("/Users/wangjing/Documents/lucene/data/").listFiles();
File[] dataFiles = file.listFiles();
if(dataFiles != null){
for(File f : dataFiles) {
if (f.isFile() && f.getName().endsWith(".txt")) {
System.out.println("正在建立索引:" + f.getCanonicalPath());
//生成Document
Document document = getDocument(f);
this.indexWriter.addDocument(document);
}
}
}else{
logger.info("找不到目录");
}
}
this.indexWriter.commit();
}else{
logger.info("找不到文件或者目录");
}
}catch (Exception e){
e.printStackTrace();
}
}
/**
* 根据file生成Document
* @param file 文件
* @return 文档结构
*/
public Document getDocument(File file){
Document document = new Document();
//document.add(new StringField("path", dataFiles[i].getAbsolutePath(),Store.YES));
document.add(new TextField("path", file.getAbsolutePath(),Store.YES));
document.add(new TextField("contents", getFileContent(file),Store.YES));
return document;
}
/**
* 获取文件内容
* @param file 文件
* @return 文件内容
*/
public static String getFileContent(File file){
String result = "";
try{
BufferedReader br = new BufferedReader(new FileReader(file));//构造一个BufferedReader类来读取文件
String s;
while((s = br.readLine())!=null){//使用readLine方法,一次读一行
result = result+s;
}
br.close();
}catch(Exception e){
e.printStackTrace();
}
return result;
}
/**
* 根据字段以及值进行查找
* @param field 字段
* @param queryString 值
*/
public void search(String field , String queryString){
try{
IndexReader reader = DirectoryReader.open(this.dir);
IndexSearcher searcher = new IndexSearcher(reader);
// Term term = new Term(field,queryString);
// TermQuery luceneQuery = new TermQuery(term);
Query query = new QueryParser(field,new StandardAnalyzer()).parse(queryString);
TopDocs result = searcher.search(query,10);
ScoreDoc[] hits = result.scoreDocs;
System.out.println("找到" + hits.length + "条记录");
for(int i=0;i<hits.length;++i) {
int docId = hits[i].doc;
Document d = searcher.doc(docId);
System.out.println((i + 1) + ". " + d.get("path") + "\t" + d.get("contents"));
}
}catch (Exception e){
e.printStackTrace();
}
}
public static void main(String[] args) {
LuceneIndex index = new LuceneIndex("/Users/wangjing/Documents/lucene/data1/");
index.search("contents","国");
}
}