这篇文章是基于上一篇文章来写的,使用的是IndexUtil类,下面的例子不在贴出整个类的内容,只贴出具体的方法内容。
3.5版本:
先写了一个check()方法来查看索引文件的变化:
/**
* 检查一下索引文件
*/
public static void check() {
IndexReader indexReader = null;
try {
Directory directory = FSDirectory.open(new File("F:/test/lucene/index"));
indexReader = IndexReader.open(directory);
// 通过reader可以有效的获取到文档的数量
// 有效的索引文档
System.out.println("有效的索引文档:" + indexReader.numDocs());
// 总共的索引文档
System.out.println("总共的索引文档:" + indexReader.maxDoc());
// 删掉的索引文档,其实不恰当,应该是在回收站里的索引文档
System.out.println("删掉的索引文档:" + indexReader.numDeletedDocs());
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (indexReader != null) {
indexReader.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
那么就下来就先跑一下建立索引方法,然后在执行以下check()方法,看看结果:
有效的索引文档:3 总共的索引文档:3 删掉的索引文档:0接下来我想删除一个索引,例子如下:
/**
* 删除索引
*/
public static void delete() {
IndexWriter indexWriter = null;
try {
Directory directory = FSDirectory.open(new File("F:/test/lucene/index"));
Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_35);
IndexWriterConfig indexWriterConfig = new IndexWriterConfig(Version.LUCENE_35, analyzer);
indexWriter = new IndexWriter(directory, indexWriterConfig);
/**
* 参数是一个选项,可以是一个Query,也可以是一个term,term是一个精确查找的值
*
* 此时删除的文档并不会被完全删除,而是存储在一个回收站中的,可以恢复
*/
// 方式一:通过Term删除
/**
* 注意Term构造器的意思,第一个参数为Field,第二个参数为Field的值
*/
indexWriter.deleteDocuments(new Term("id", "1"));
// 方式二:通过Query删除
/**
* 这里就要造一个Query出来,删掉查处的索引
*/
QueryParser queryParser = new QueryParser(Version.LUCENE_35, "content", analyzer);
// 创建Query表示搜索域为content包含Lucene的文档
Query query = queryParser.parse("Lucene");
// indexWriter.deleteDocuments(query);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (indexWriter != null) {
indexWriter.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}看看测试:
@Test
public void testDelete() {
IndexUtil.delete();
IndexUtil.check();
}执行过后:
有效的索引文档:2 总共的索引文档:3 删掉的索引文档:1此时被删掉的文档跑到了回收站中,并没有被彻底删除,我们上面使用的是删term的方式,那么使用query删行不行呢,那么现在把注释换一换:
// indexWriter.deleteDocuments(new Term("id", "1"));
// 方式二:通过Query删除
/**
* 这里就要造一个Query出来,删掉查处的索引
*/
QueryParser queryParser = new QueryParser(Version.LUCENE_35, "content", analyzer);
// 创建Query表示搜索域为content包含Lucene的文档
Query query = queryParser.parse("Lucene");
indexWriter.deleteDocuments(query);再跑一下测试方法:
有效的索引文档:1 总共的索引文档:3 删掉的索引文档:2看看,被删除的文档又多了一个,因为我们query查出的文档和id为1的文档不是同一个,目前了解了删除的两种方式怎么使用了吧。
/**
* 恢复删除的索引
*/
public static void unDelete() {
// 使用IndexReader进行恢复
IndexReader indexReader = null;
try {
Directory directory = FSDirectory.open(new File("F:/test/lucene/index"));
// 恢复时,必须把IndexReader的只读(readOnly)设置为false
// 索引没有改变可以使用true,但现在是恢复删除的索引,显然是改变过的,所以只能是false
indexReader = IndexReader.open(directory, false);
indexReader.undeleteAll();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (indexReader != null) {
indexReader.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}跑一下测试:
@Test
public void testUnDelete() {
IndexUtil.unDelete();
IndexUtil.check();
}结果为:
有效的索引文档:3 总共的索引文档:3 删掉的索引文档:0全部恢复了吧,很不错吧
但是我现在有发现刚才没有删错,我要把索引彻底删除,怎么弄呢,我们回过头来再试,我现在吧删除索引的两种方式的注释都打开,执行一下删除方法是不是得到这样的结果啊:
有效的索引文档:1 总共的索引文档:3 删掉的索引文档:2然后看看彻底删除的代码:
/**
* 强制删除
*/
public static void forceDelete() {
IndexWriter indexWriter = null;
try {
Directory directory = FSDirectory.open(new File("F:/test/lucene/index"));
Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_35);
IndexWriterConfig indexWriterConfig = new IndexWriterConfig(Version.LUCENE_35, analyzer);
indexWriter = new IndexWriter(directory, indexWriterConfig);
indexWriter.forceMergeDeletes();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (indexWriter != null) {
indexWriter.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}执行一下测试代码:
@Test
public void testForceDelete() {
IndexUtil.forceDelete();
IndexUtil.check();
}结果如下:
有效的索引文档:1 总共的索引文档:1 删掉的索引文档:0此时两个索引文档被彻底的删掉了。这么长都在讲删除的事,那么Lucene是怎么更新索引的呢,记下来看看是如何更新索引的:
注:先把索引文件删除,重新建索引
/**
* 更新索引
*/
public static void update() {
IndexWriter indexWriter = null;
try {
Directory directory = FSDirectory.open(new File("F:/test/lucene/index"));
Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_35);
IndexWriterConfig indexWriterConfig = new IndexWriterConfig(Version.LUCENE_35, analyzer);
indexWriter = new IndexWriter(directory, indexWriterConfig);
/**
* Lucene并没有提供更新,这里的更新操作其实是如下两个操作的合集 先删除之后再添加
*/
Document document = new Document();
document.add(new Field("id", "11", Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS));
document.add(new Field("author", authors[0], Field.Store.YES, Field.Index.NOT_ANALYZED));
document.add(new Field("title", titles[0], Field.Store.YES, Field.Index.ANALYZED));
document.add(new Field("content", contents[1], Field.Store.NO, Field.Index.ANALYZED));
indexWriter.updateDocument(new Term("id", "1"), document);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (indexWriter != null) {
indexWriter.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}注意上边这段代码,我使用的content是id为2的content,它包含“Lucene”,我一会要用它测试,注意比对结果
此时执行一下更新索引:
@Test
public void testUpdate() {
IndexUtil.update();
IndexUtil.check();
}结果为:
有效的索引文档:3 总共的索引文档:4 删掉的索引文档:1结果是这样的,惊讶吗,我们一起来算算,有效的文档删掉一个添加一个是不是3个,没错吧,总共的文档数是三个加一个,引文删掉的文档也算啊,没有彻底删掉,在回收站里,然后我们执行一下search()方法,看看结果:
/**
* 搜索
*/
public static void search() {
IndexReader indexReader = null;
try {
// 1、创建Directory
Directory directory = FSDirectory.open(new File("F:/test/lucene/index"));
// 2、创建IndexReader
indexReader = IndexReader.open(directory);
// 3、根据IndexReader创建IndexSearch
IndexSearcher indexSearcher = new IndexSearcher(indexReader);
// 4、创建搜索的Query
// 使用默认的标准分词器
Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_35);
// 在content中搜索Lucene
// 创建parser来确定要搜索文件的内容,第二个参数为搜索的域
QueryParser queryParser = new QueryParser(Version.LUCENE_35, "content", analyzer);
// 创建Query表示搜索域为content包含Lucene的文档
Query query = queryParser.parse("Lucene");
// 5、根据searcher搜索并且返回TopDocs
TopDocs topDocs = indexSearcher.search(query, 10);
// 6、根据TopDocs获取ScoreDoc对象
ScoreDoc[] scoreDocs = topDocs.scoreDocs;
for (ScoreDoc scoreDoc : scoreDocs) {
// 7、根据searcher和ScoreDoc对象获取具体的Document对象
Document document = indexSearcher.doc(scoreDoc.doc);
// 8、根据Document对象获取需要的值
System.out.println("id : " + document.get("id"));
System.out.println("author : " + document.get("author"));
System.out.println("title : " + document.get("title"));
/**
* 看看content能不能打印出来,为什么?
*/
System.out.println("content : " + document.get("content"));
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (indexReader != null) {
indexReader.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
} @Test
public void testSearch() {
IndexUtil.search();
}id : 2 author : Tony title : Hello Lucene content : null id : 11 author : Darren title : Hello World content : null查出来了两条,说明更新成功了
我再把id为3的索引也更新一下:
Document document = new Document();
document.add(new Field("id", "11", Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS));
document.add(new Field("author", authors[0], Field.Store.YES, Field.Index.NOT_ANALYZED));
document.add(new Field("title", titles[0], Field.Store.YES, Field.Index.ANALYZED));
document.add(new Field("content", contents[1], Field.Store.NO, Field.Index.ANALYZED));
indexWriter.updateDocument(new Term("id", "3"), document);执行一下update()方法,看看结果:
有效的索引文档:3 总共的索引文档:5 删掉的索引文档:2问题来了,随着索引文件更新次数的增加,索引文件是不是会越来越多啊,那我们是不是有办法合并一下优化一下呢,下面来看Lucene是怎么合并索引文件的:
/**
* 合并索引
*/
public static void merge() {
IndexWriter indexWriter = null;
try {
Directory directory = FSDirectory.open(new File("F:/test/lucene/index"));
Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_35);
IndexWriterConfig indexWriterConfig = new IndexWriterConfig(Version.LUCENE_35, analyzer);
indexWriter = new IndexWriter(directory, indexWriterConfig);
// 会将索引合并为2段,这两段中的被删除的数据会被清空
/**
* 特别注意:
*
* 此处Lucene在3.5之后不建议使用,因为会消耗大量的开销,Lucene会根据情况自动处理的
*/
// 把索引合并为两段
indexWriter.forceMerge(2);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (indexWriter != null) {
indexWriter.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}执行一下测试:
@Test
public void testMerge() {
IndexUtil.merge();
IndexUtil.check();
}结果为:
有效的索引文档:3 总共的索引文档:3 删掉的索引文档:0索引文件数恢复正常了,这里有个问题,Lucene的合并索引方法或优化索引方法不建议人为调用,会消耗很多资源,并且Lucene会自动优化索引,索引不用担心索引文件一直变大变多这个问题。
4.5版本:
5.0版本:
4.5版本和5.0版本稍后更新
原文地址:http://blog.csdn.net/zpf336/article/details/45170965