这里面用的是比较新的Lucene4.10.2 做的一个实例。(lucene的索引不能太大,要不然效率会很低。大于1G的时候就必须考虑分布索引的问题)
先介绍一下Lucene的几个参数意义:
IndexWriter:lucene中最重要的的类之一,它主要是用来将文档加入索引,同时控制索引过程中的一些参数使用。
Analyzer:分析器,主要用于分析搜索引擎遇到的各种文本。常用的有StandardAnalyzer分析器,StopAnalyzer分析器,WhitespaceAnalyzer分析器等。
Directory:索引存放的位置;lucene提供了两种索引存放的位置,一种是磁盘,一种是内存。一般情况将索引放在磁盘上;相应地lucene提供了FSDirectory和RAMDirectory两个类。
Document:文档;Document相当于一个要进行索引的单元,任何可以想要被索引的文件都必须转化为Document对象才能进行索引。
Field:字段。
IndexSearcher:是lucene中最基本的检索工具,所有的检索都会用到IndexSearcher工具;
Query:查询,lucene中支持模糊查询,语义查询,短语查询,组合查询等等,如有TermQuery,BooleanQuery,RangeQuery,WildcardQuery等一些类。
QueryParser: 是一个解析用户输入的工具,可以通过扫描用户输入的字符串,生成Query对象。
话说Lucene就两个重要步骤,一个是创建索引,一个是查询索引,首先看下如何创建索引的代码。
import util.IOUtil;
/**
* @author ${朱良兴}
*2015-1-26
*/
public class CreateIndexer { public void createIndex() throws Exception{ IOUtil utils= new IOUtil();
// 一、创建索引
// 内存索引模板
Directory dir = new RAMDirectory();
Analyzer analyzer = new StandardAnalyzer();
IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE_4_10_2,
analyzer);
IndexWriter indexWriter = new IndexWriter(dir, config);
//文件位置。
File fileDir = new File( "E:\\ftp" );
String path = "E:\\ftp";
long startTime = new Date().getTime();
String id;
//获取所有的文件名。
List <String> fileList = utils.getFileName(path);
for(int i=0; i<fileList.size();i++){
String content = utils.getFileContent(new File(fileList.get(i)), "GBK");
id ="id"+i;
indexPost(id, content);
} // 测试一下索引的时间
long endTime = new Date().getTime();
System.out .println( " 这花费了 " + (endTime - startTime) + " 毫秒来把文档增加到索引里面去! " + fileDir.getPath());
indexWriter.close(); }
@SuppressWarnings("deprecation")
private static void indexPost(String id,String content){
/* 这里放索引文件的位置 */
File indexDir = new File("E:\\index");
Analyzer analyzer = new IKAnalyzer();
TextField postIdField = new TextField("id", id, Store.YES); // 不要用StringField
TextField postContentField = new TextField("content", content, Store.YES); Document doc = new Document();
doc.add(postIdField);
doc.add(postContentField);
IndexWriterConfig iwConfig = new IndexWriterConfig(Version.LUCENE_4_10_2, analyzer);
iwConfig.setOpenMode(IndexWriterConfig.OpenMode.CREATE_OR_APPEND);
try {
Directory fsDirectory = FSDirectory.open(indexDir);
IndexWriter indexWriter = new IndexWriter(fsDirectory, iwConfig);
indexWriter.addDocument(doc);
indexWriter.close();
} catch (Exception e) {
e.printStackTrace();
} }
第二就是查询:
/**
* 查询索引
* @author ${朱良兴}
*2015-1-26
*/
public class DoSearch {
public static void main(String[] args) throws Exception {
//创建索引
CreateIndexer createIndexer = new CreateIndexer();
createIndexer.createIndex();
Analyzer analyzer = new IKAnalyzer();
File indexDir = new File("E:\\index");
try {
Directory fsDirectory = FSDirectory.open(indexDir);
DirectoryReader ireader = DirectoryReader.open(fsDirectory);
IndexSearcher isearcher = new IndexSearcher(ireader);
QueryParser qp = new QueryParser("content", analyzer); //使用QueryParser查询分析器构造Query对象
qp.setDefaultOperator(QueryParser.AND_OPERATOR);
Query query = qp.parse("么么哒"); // 搜索Lucene
long beginTime = new Date().getTime();
TopDocs topDocs = isearcher.search(query , 100); //搜索相似度最高的100条记录
long endTime = new Date().getTime();
System.out.println("命中:" + topDocs.totalHits);
System.out.println("搜索花费的时间:"+(endTime-beginTime)+"毫秒");
ScoreDoc[] scoreDocs = topDocs.scoreDocs;
for (int i = 0; i < topDocs.totalHits; i++){
Document targetDoc = isearcher.doc(scoreDocs[i].doc);
System.out.println("内容:" + targetDoc.toString());
} } catch (Exception e) { }
}
}
用到的工具类代码:
package util;import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;/**
* IO 工具类。
* @author ${朱良兴}
*2015-1-26
*/
public class IOUtil{ List<String> fileList = new ArrayList<String>();
/**
* 根据文件的全路径获得所有的文件内容
* @param fileName
* @param charset
* @return
* @throws Exception
*/
public String getFileContent(File fileName, String charset) throws Exception{
BufferedReader reader = new BufferedReader( new InputStreamReader(
new FileInputStream(fileName), charset));
String line = new String();
String temp = new String();
while ((line = reader.readLine()) != null ) {
temp += line;
}
reader.close();
return temp;
}
/**
* 获取所有的文件名
* @param path
* @return
* @throws Exception
*/
public List<String> getFileName(String path) throws Exception{ String filenName ="";
//文件位置。
File fileDir = new File(path);
File[] textFiles = fileDir.listFiles();
if (textFiles!=null){ // 增加document到索引去
for ( int i = 0 ; i < textFiles.length; i ++ ) {
if (textFiles[i].isFile()) {
System.out.println( " File " + textFiles[i].getCanonicalPath()
+ " 正在被索引. " );
filenName=textFiles[i].getCanonicalPath();
fileList.add(filenName); }else{ getFileName(textFiles[i].getCanonicalPath());
}
}
}
return fileList; }
}
这里是和IK Analyzer 结合使用的简单示例