package com.boryou.dyf.lucene;
import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.LimitTokenCountAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.index.CorruptIndexException;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.LogDocMergePolicy;
import org.apache.lucene.index.Term;
import org.apache.lucene.queryParser.ParseException;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.search.BooleanClause;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.Sort;
import org.apache.lucene.search.SortField;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.store.LockObtainFailedException;
import org.apache.lucene.store.SimpleFSDirectory;
import org.apache.lucene.util.Version;
import org.wltea.analyzer.lucene.IKAnalyzer;
/*
* @author: duyafei
* @time: 2011.10.29
*
* @modify 2011.11.1 重构方法 queryIndex,移除方法中,字段名 和字段的值两个参数,以及方法中关于query对象的部分
* 添加公共方法 addQuery ,clearQuery ,
* 添加私有成员 _bQuery,用于实现多字段查询
*
* @modify 2011.11.4 如果无日期项,默认取最近日期
*
* @modify 2011.11.5 修改构造查询部分,构造无分词的查询条件
*
*@descript: 封装lucene调用类
*
* */
public class LuceneIndex {
public LuceneIndex()
{
}
//获取查询条件对象
/*
* @author shuaizhihu
* @time 2011.11.5
* @argument: field 要查询的字段
* queryString 字段的值
* fenci 查询是否分词,true 分词,false 不分词
* analyzer 分词器对象
*
* */
public Query getQuery(String field,String queryString,boolean fenci,Analyzer analyzer){
//根据是否分词,构造查询条件
if(fenci){
//构造分词查询条件
QueryParser qrParser = new QueryParser(Version.LUCENE_31,
field,
analyzer);
try
{
return qrParser.parse(queryString);
} catch (ParseException e)
{
e.printStackTrace();
}
}else{
//构造不分词查询条件
Term term=new Term(field,queryString);
return new TermQuery(term);
}
return null;
}
//add 2011.11.1 多字段查询对象
private BooleanQuery _bQuery = null;
//add 2011.11.4 添加_sName 变量,用于存储要查询的文件的名称
private String _sName = null;
//用于对多字段查询对象,插入一般查询对象
//@argument : strField 要查询的 字段名
// strValue 要查询的 字段的值
public void addQuery(String strField, String strValue){
if (null == _bQuery)
{
_bQuery = new BooleanQuery();
}
if ("name".equals(strField))
{
_sName = strValue;
}
//构造查询分析器
// QueryParser qrParser = new QueryParser(Version.LUCENE_31,
// strField,
// luciAnalyzer);
//构造查询条件
// Query query = null;
// try
// {
// query = qrParser.parse(strValue);
// } catch (ParseException e)
// {
// e.printStackTrace();
// }
Analyzer luciAnalyzer = new IKAnalyzer();
//构造不分词的查询
Query query = getQuery(strField, strValue, false, luciAnalyzer);
_bQuery.add(query, BooleanClause.Occur.MUST);
}
//将多字段查询对象清空
public void clearQuery(){
this._bQuery = null;
}
//异常类,用于处理程序中文件夹使用异常
/*
* @author : dyf
* @time : 2011.10.31
* */
class FileException extends Exception {
public FileException(){}
public FileException(String msg){
super(msg);
}
/**
*
*/
private static final long serialVersionUID = 1727936850431811905L;
}
//文件夹路径预处理类
/*
* @descripte: 用于对输入的文件路径,进行必要的处理,抛出需要的异常信息
*
* */
class FolderDispose {
public FolderDispose(){}
//用与对输入的文件夹进行必要处理
/*
* @descripte: 根据输入的路径和路径代表的意义,抛出响应的异常
* @argument: filePath 输入的文件夹路径
* type 代表输入路径的意义,int型,各个值的意义对应如下:
* 值为1 ,文件路径指向被建立索引的源文件夹
* 值为2, 文件路径指向存放索引文件的路径
* 值为3, 文件路径指向合并索引中,源文件夹的路径
* 值为4, 文件路径指向合并索引中,目的文件夹的路径
* */
public void testDir(String filePath, int type)throws FileException
{
File fDir = new File(filePath);
FileException exception = null;
switch (type)
{
case 1: //文件路径指向被建立索引的源文件夹
{
//想要建立索引的文件夹不存在。
if ( (!fDir.exists()))
{
exception =
new FileException(filePath
+ " 指定文件或文件夹不存在!!");
throw exception;
}
//源文件夹为空
else if( fDir.isDirectory() && 0 == (fDir.listFiles()).length )
{
exception =
new FileException(filePath
+ " 想要建立索引的文件为空,请重新指定!!");
throw exception;
}
}
break;
case 2: //文件路径指向存放索引文件的路径
{
//存放索引文件的文件夹
//如果文件夹已存在切不为空
if (fDir.exists() && fDir.isDirectory() && 0 != (fDir.list()).length )
{
exception =
new FileException(filePath
+ " 存放索引文件的文件夹不为空,请清空文件夹或者选择合并索引操作!!");
throw exception;
}
}
break;
case 3: //文件路径指向合并索引中,源文件夹的路径
{
//存放源索引文件的文件夹
//文件夹不存在或者为空
if ( !fDir.exists() )
{
exception =
new FileException(filePath
+ " 源索引文件夹不存在!");
throw exception;
}
else if ( fDir.isDirectory() && 0 == (fDir.list()).length) {
exception =
new FileException(filePath
+ " 源索引文件夹为空!");
}
}
break;
case 4: //文件路径指向合并索引中,目的文件夹的路径
{
//目的文件夹为空或者不存在
if ( !fDir.exists() )
{
exception = new FileException(filePath
+ " 目的文件夹不存在!" );
throw exception;
}
else if ( fDir.isDirectory() && 0 == ((fDir.list()).length) ){
exception = new FileException(filePath
+ " 目的文件夹为空!!");
}
}
break;
default:
break;
}
}
}
//创建索引
/*
* @author dyf
*
* @argument : fileDir 要建立索引的文件夹,indexDir 建立好的索引文件存放位置
*
* @modify 2011.11.1 修改field "date" 的形式, 从"yyyy_MM_dd-1"改成 "yyyyMMdd"
*
* */
public void createIndex(String fileDir, String indexDir){
//预处理文件路径
FolderDispose fDispose = new FolderDispose();
try
{
fDispose.testDir(fileDir, 1);
fDispose.testDir(indexDir, 2);
} catch (FileException e1)
{
e1.printStackTrace();
}
//被索引的文件所在文件夹
File fDir = new File(fileDir);
//索引文件存放的文件夹
File IndexDir = new File(indexDir);
//获取文件目录及其子目录下的所有文件。
ArrayList<File> arrFile = new ArrayList<File>();
if (fDir.isDirectory()) {
arrFile.addAll( cycleFileDir(fDir) );
}
else {
arrFile.add(fDir);
}
// 1.建立写索引
//分词器
Analyzer luceneAnaly = new IKAnalyzer();
//索引文件路径
Directory indexDirect = null;
try {
indexDirect= new SimpleFSDirectory(IndexDir);
} catch (IOException e) {
e.printStackTrace();
}
//写索引句柄
IndexWriter ind