以下代码把lucene基本操作方法封装在了IndexUtil类中,其中考虑到创建indexReader开销过大,就设计了单实例模式。注释中会穿插些4.x版本与3.x版本的不同之处。
package lucene;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.StringField;
import org.apache.lucene.document.TextField;
import org.apache.lucene.document.Field.Store;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.Term;
import org.apache.lucene.index.IndexWriterConfig.OpenMode;
import org.apache.lucene.queryparser.classic.ParseException;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.lucene.util.Version;
import pojo.LuceneBeans;
public class IndexUtil {
private static Directory directory = null;
private static IndexReader reader = null;
/**
* 设置存储路径
* @return
*/
public static String getIndexDir(){
//得到.class文件所在路径
String classpath = LuceneUtil.class.getResource("/").getPath();
//将class中的%20替换成为空格
classpath = classpath.replaceAll("%20", " ");
//索引存储位置:WEB-INF/classes/index
String path = classpath+"index/";
return path;
}
public IndexUtil(){
try {
//存储方式有CompoundFileDirectory, FileSwitchDirectory, FSDirectory,
//NRTCachingDirectory, RAMDirectory……等分别对应的不同方式
//用FSDirectory的好处就在于它会自动帮你分配该使用哪种方式
directory = FSDirectory.open(new File(getIndexDir()));
//3.x是reader=IndexReader.open(directory);
//但4.x后已经不建议使用,改成了DirectoryReader.open(directory)
reader = DirectoryReader.open(directory);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 创建IndexWriter
* @return
*/
public static IndexWriter getIndexWriter(){
//创建分词器,分词器可根据自己需求去自定义创建,此处以lucene自带的标准分词器分词
Analyzer analyzer=new StandardAnalyzer(Version.LUCENE_45);
IndexWriter indexWriter = null;
try {
IndexWriterConfig iwConfig = new IndexWriterConfig(Version.LUCENE_45, analyzer);
iwConfig.setOpenMode(OpenMode.CREATE_OR_APPEND);
indexWriter = new IndexWriter(directory, iwConfig);
return indexWriter;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
//--------省略余下方法代码
嗯~创建索引前我们需要先获得IndexWriter,其实步骤就像你往数据库中插入一条数据(document),得再这条数据中加入字段(Field),得给这个字段做个说明(Store、Index)……
/**
* 批量创建索引
* @param list
* @return
*/
public boolean createIndexList(List<LuceneBeans> list){
boolean result = false;
IndexWriter indexWriter = IndexUtil.getIndexWriter();
try {
if(list!=null&&list.size()>0){
Document doc = null;
for(int i=0;i<list.size();i++){
doc = new Document();
LuceneBeans lb = list.get(i);
doc.add(new StringField("id",lb.getId(),Store.YES));
doc.add(new TextField("title",lb.getTitle(),Store.YES));
doc.add(new TextField("introduce",lb.getIntroduce(),Store.YES));
doc.add(new StringField("addtime",lb.getAddtime(),Store.YES));
doc.add(new StringField("category",lb.getCategory(),Store.YES));
indexWriter.addDocument(doc);
indexWriter.commit();
result = true;
}
}
} catch (IOException e) {
e.printStackTrace();
}finally{
if(indexWriter!=null){
try {
indexWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return result;
}
之前3.x版本是这样写的:
doc.add(new Field("id",lb.getI(),Field.Store.YES,Field.Index.NOT_ANALYZED_NO_NORMS));
那我们就顺便来分析下store、index
(存储域选项)Store判断是否把域存入文件(yes存入,可还原;no不存入,不可还原但可被索引)
(索引域选项)Index:
//|----ANALYZED进行分词和索引,适用于标题、内容等
//|----NO_ANALYZED进行索引但是不进行分词,身份号、姓名、ID等,适用于精确搜索
//|----ANALYZED_NOT_NORMS进行分词但不存储norms信息,这个norms中包括了创建索引的时间和权值等信息
//|----NOT_ANALYZED_NOT_NORMS既不进行分词也不存储norms信息
但4.x之后就改变了,它需要更为精确的StringField、TextField、IntField……
那为什么4.x版本只写了Store而没Index?还是让我们看看官方文档上的描述吧:
先看TxetField:自动分词
再看看StringField:不分词
所以,4.x有很多写法是与3.x不同的,虽然还可以向下兼容,但总是要跟着时代的脚步前进嘛!