Lucene索引的基本操作
在上一篇文章中,我们对Lucene有了一个简单的入门,学习了Lucene给我们提供的一些重要的类,接下来我们就来使用这些类完成对索引的一些基本操作。
一、索引的创建
索引的创建主要分为如下几步:
- 初始化IndexWriter对象,指明索引存放的位置,处理索引分词的分词器。
- 初始化Document对象,添加文件,开始索引过程。
根据上面的步骤,我们来看下面的代码:
/**
*
* @author tanjie
* 创建时间: 2015-11-5 上午9:00:25
* 描述: 索引的创建
*/
public void createIndex() {
IndexWriter indexWriter = null;
Document document = null;
try {
Thread.sleep(2000);
//初始化IndexWriter对象
indexWriter = LuceneUtils.getIndexWriter();
File file = new File("E:\\luceneData");
File[] listFile = file.listFiles();
//为Document添加Field,Field即存储文档的属性
for (int i = 0; i < listFile.length; i++) {
if (listFile[i].isFile()) {
//初始化document对象
document = LuceneUtils.getDocument(listFile[i]);
//通过indexWriter添加文档到索引中
System.out.println("正在建立索引:" + listFile[i] + "");
indexWriter.addDocument(document);
}
}
} catch (IOException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
} finally{
if(null != indexWriter){
try{
indexWriter.close();
}catch(IOException e){
e.printStackTrace();
}
}
}
}
}
执行完上面的代码,在你指定的索引存放的目录,我的本地是E:\luceneIndex,会有下面的索引文件。
二、索引的删除
索引的删除是Lucene提供的一个非常重要的操作,当我们建立的索引失效了,或者索引太多,需要删除一些不需要的索引时,就有必要对索引进行相应的删除操作了。
/**
*
* @author tanjie
* 创建时间: 2015-11-5 上午9:00:25
* @param field 删除索引对应的域
* @param keyword 删除索引对应的域里对应的词
* 描述: 索引的删除
*/
public void deleteIndex(String field,String keyword) {
long startTime = new Date().getTime();
IndexWriter indexWriter = null;
try {
indexWriter = LuceneUtils.getIndexWriter();
//表示删除域field里面词为keyword的索引
indexWriter.deleteDocuments(new Term(field,keyword));
indexWriter.commit();
long endTime = new Date().getTime();
System.out.println("删除索引耗时:" + (endTime - startTime) + "ms\n");
} catch (IOException e) {
e.printStackTrace();
} finally {
if (null != indexWriter) {
try {
indexWriter.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
三、索引的更新
更新文档是索引处理的一部分,该操作也被称为重新编制索引。在Lucene中,实际上没有索引的更新操作,但我们执行索引的更新时,Lucene实际上执行了2步,第一步是原有索引的删除,第二步是更新索引的新建工作。
/**
* @author tanjie 创建时间: 2015-10-22 上午11:10:15
描述: 更新索引
* @param field 更新内容的域
* @param text 更新的内容
*/
public void update(String field,String text) {
long startTime = new Date().getTime();
IndexWriter indexWriter = null;
try {
//初始化indexWriter对象
indexWriter = LuceneUtils.getIndexWriter();
Document doc1 = new Document();
doc1.add(new TextField("content", text, Store.YES));
indexWriter.updateDocument(new Term(field, text), doc1);
indexWriter.commit();
long endTime = new Date().getTime();
System.out.println("更新索引耗时:" + (endTime - startTime) + "ms\n");
} catch (IOException e) {
e.printStackTrace();
}
}
四、索引的搜索
刚刚,我们对E:\luceneData目录下面的内容进行了索引的创建,创建的索引存放在了E:\luceneIndex里面,接下来,我们可以对索引进行搜索
/**
*
* @author tanjie
* 创建时间: 2015-11-3 下午4:32:33
* 描述: Lucene根据索引进行搜索
* @param keyword 搜索的关键字
* @param field 搜索的域
*
*/
public void createSearcher(String keyword, String field) {
//具体方法实现见下文
TopDocs topDocs = LuceneUtils.search(keyword, field);
//具体方法实现见下文
LuceneUtils.printResult(topDocs);
}
/**
*
* @author tanjie 创建时间: 2015-10-22 上午10:02:20 描述: 返回查询结果
* @param keyword 查询关键字
* @param field 查询哪个域
* @return TopDocs
*/
public static final TopDocs search(String keyword, String field) {
TopDocs topDocs = null;
try {
analyzer = new StandardAnalyzer(Version.LUCENE_4_9);
//初始化IndexSearch
IndexSearcher searcher = new IndexSearcher(DirectoryReader.open(FSDirectory.open(new File("E:\\luceneIndex"))));
//第二个参数表示搜索哪个域
QueryParser parser = new QueryParser(Version.LUCENE_4_9, field,
analyzer);
//将关键字包装成Query对象
Query query = parser.parse(keyword);
topDocs = searcher.search(query, 100);
} catch (Exception e) {
e.printStackTrace();
}
return topDocs;
}
/**
*
* @author tanjie 创建时间: 2015-10-22 上午10:02:46 描述: 打印结果
* @param results 搜索返回的
*/
public static void printSearchResult(TopDocs topDocs){
ScoreDoc[] scoreDoc = topDocs.scoreDocs;
if (scoreDoc.length > 0) {
for (int i = 0; i < scoreDoc.length; i++) {
try {
Document doc = searcher.doc(scoreDoc[i].doc);
System.out.print("这是第" + (i + 1) + "个检索到的结果");
} catch (Exception e) {
e.printStackTrace();
}
}
}else{
System.out.print("没有相关结果搜索到");
}
}
上面的方法在一个工具类里面,下面我们写测试类来对刚刚我们创建的索引进行搜索
/**
*
* 类名: TestLuceneCRUD.java 包: com.travelsky.pss.react.cn.lucene.oneByone
* 描述: 测试Lucene索引的基本操作
*
* @author tanjie 创建时间: 2015-10-21 下午2:45:49
* @version V1.2.0
*/
public class TestLuceneCRUD {
private String queryValue = "人";
private String field = "content";
private LuceneIndexCreatAndSearch luceneIndexCreatAndSearch = null;
static {
luceneIndexCreatAndSearch = new LuceneIndexCreatAndSearch();
}
@Test
public void testIndexQuery() {
luceneIndexCreatAndSearch.createSearcher(queryValue, field);
}
上面的测试类,我们搜索了域为content的存在词人的文档,执行上面的测试类,结果如下