先介绍一个使用 IndexWriter 清空索引的功能。因为我们在测试的时候,须要将之前创建的索引都删掉(当然手动删除索引文件也是可以的)。
删除索引和数据库事务一样,先删除到一个回收站中,然后 commit() 以后才会真正删除。
还要强调的一点是 IndexWriter 使用完毕以后是要关闭的。
/**
* 删除所有索引文件
*/
public void deleteAll() throws IOException{
IndexWriter indexWriter = getIndexWriter();
indexWriter.deleteAll();
indexWriter.commit();
indexWriter.close();
System.out.println("索引目录下的所有索引文件清空完毕!");
}
使用 Lucene 进行搜索的步骤是:
1、通过 Directory 对象创建 IndexReader 对象
2、通过 IndexReader 对象创建 IndexSearcher 对象
3、创建 Query 对象,传入查询条件,或者通过 QueryParser 对象生成 Query 对象;
4、通过向 IndexSearch 对象中传入 Query 对象,使用 search 方法查询结果 TopDocs 。其实到这里查询结果就出来了,但是我们还要对查询的结果进行进一步的处理;
TopDocs 的含义是 Top Documents,意思就是排名在前面的 Document,Document 在上一节中我们说到,它的含义就相当于一条数据,我们就可以通过 Document 得到数据的相关信息。
5、 从 TopDocs 中得到评分信息, 即 scoreDocs,遍历 scoreDocs 属性,通过 IndexSearch 的 doc() 方法(传入每一个 ScoreDoc 的 doc 属性,类似 id 这个概念),就可以恢复创建索引的时候创建的 Document;
这里说起来晦涩难懂,大家看一看代码就很清楚了。我第一遍写的时候感觉很复杂,写多了,其实都还好。
上面说的这些个步骤,相当于是一个模式,以后我们写搜索的时候,无非就是在这样的一个流程上做一些改动。
/**
* 搜索方法 1:针对某个“不分词的”特定项的搜索方法
*/
public void search01() {
try {
IndexReader reader = DirectoryReader.open(directory);
IndexSearcher searcher = new IndexSearcher(reader);
TermQuery query = new TermQuery(new Term("email","liweipower2015@gmail.com"));
TopDocs tds = searcher.search(query, 10);
Document doc = null;
for(ScoreDoc sd:tds.scoreDocs) {
doc = searcher.doc(sd.doc);
// doc.getValues("email")[1]
System.out.println("doc => "+sd.doc+ " 得分 score => "+sd.score + " name => " + doc.get("name") + " email => " + doc.get("email") + " id => "+doc.get("id"));
}
reader.close();
} catch (CorruptIndexException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
上面的这个例子中的 TermQuery 指的是针对不分词的字段的特定的项进行搜索,也就是我们要找出 email 字段的值为 “liweipower2015@gmail.com” 的数据的前 10 条。
我们还可以对分词的特定项进行搜索。例如,我们的 Query 对象可以这样创建:
TermQuery query = new TermQuery(new Term("content","like"));
content 这个字段是我们经过分词以后的,只要是分词以后的结果中还有 “like” 这个单词的数据都会被我们搜索出来。
IndexReader 有三个重要的方法,这里我们要清楚,我们可以通过下面的这三个方法查看哪些索引信息是被我们删除了,即哪些是删除在回收站里,哪些是真正删除了。IndexReader 使用完毕以后也是要关闭的。
IndexReader reader = DirectoryReader.open(directory);
// 通过 IndexReader 可以获取到文档的数量
System.out.println("numDocs => "+reader.numDocs());
System.out.println("maxDocs => "+reader.maxDoc());
System.out.println("deleteDocs => "+reader.numDeletedDocs());
reader.close();
更新单个索引信息(先删除再添加)
/**
* 索引的更新:
* 其实,从来就没有索引的更新操作,实际上是先将索引删除,而后增加
* 我们可以通过索引的查询方法进行验证,即 IndexReader 的 numDocs()、maxDoc()、numDeletedDocs() 方法
*/
public void update() {
IndexWriter writer = null;
try {
writer = getIndexWriter();
/*
* Lucene并没有提供更新,这里的更新操作其实是如下两个操作的合集
* 先删除之后再添加
*/
Document doc = new Document();
doc.add(new StringField("id","7",Field.Store.YES));
doc.add(new StringField("email","liweipower2015@gmail.com",Field.Store.YES));
doc.add(new TextField("content","good good study",Field.Store.NO));
doc.add(new StringField("name","liweiwei",Field.Store.YES));
writer.updateDocument(new Term("id","1"), doc);
} catch (CorruptIndexException e) {
e.printStackTrace();
} catch (LockObtainFailedException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if(writer!=null) writer.close();
} catch (CorruptIndexException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
单条索引信息的删除,要记得使用 commit() 方法提交删除。
/**
* 这个方法演示了删除到一个“回收站”的方法
*/
public void delete() {
IndexWriter writer = null;
try {
writer = getIndexWriter();
// 参数是一个选项,可以是一个Query,也可以是一个term,term是一个精确查找的值
// 此时删除的文档并不会被完全删除,而是存储在一个回收站中的,可以恢复
writer.deleteDocuments(new Term("id","6"));
writer.commit();
} catch (CorruptIndexException e) {
e.printStackTrace();
} catch (LockObtainFailedException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if(writer!=null) writer.close();
} catch (CorruptIndexException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
但是这样的删除,还仅仅只是删除到回收站中,还有可能被搜索到。我们可以使用 IndexWriter 对象的 forceMergeDeletes() 方法清空“回收站”中的索引。看下面的例子。
/**
* 只调用这个方法,就可以把“删除缓存”(回收站)中删除缓存清空
* 即 deleteDocs() 方法查询返回 0
*/
public void forceDelete() {
IndexWriter writer = null;
try {
writer = getIndexWriter();
writer.forceMergeDeletes();
} catch (CorruptIndexException e) {
e.printStackTrace();
} catch (LockObtainFailedException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if(writer!=null) writer.close();
} catch (CorruptIndexException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}