19) 第二章 索引:用IndexReader删除文档

 

除了IndexWriter外,IndexReader也可以用来删除文档。那么两者之间有什么区别呢?

 

  A. IndexReader可以按文档id删除一个文档。

    IndexReader用来删除文档的核心方法为:

public synchronized void deleteDocument(int docNum) throws StaleReaderException, CorruptIndexException, LockObtainFailedException, IOException {
    ensureOpen();
    acquireWriteLock();
    hasChanges = true;
    doDelete(docNum);
}

    很显然,这是一个模板方法,其中acquireWriteLock默认为空实现,doDelete方法强制子类实现。

    这个方法可以让你通过IndexReader方便的查出结果集,然后删掉其中的某条数据。

 

  B. IndexReader也提供按Term删除的方法:

 

int deleteDocuments(Term term);

    然而,此方法的实现中依然调用了deleteDocument(int docNum); 不同与IndexWriter中对应的方法,此方法可以立即返回执行结果,而IndexWriter会缓存待删除的Term,并在之后的时间里执行删除操作。

 

  C. IndexWriter可以通过Query删除。

    如同通过Term删除,其实你完全可以实现自己的Query删除方式。只需要通过Query查出结果,用deleteDocument(int docNum);一一删除。

 

值得注意的是,IndexReader会以“写”方式完成删除。这就意味着,在执行删除操作前,必须关闭所有在此索引上打开的IndexWriter,反之亦然。因此,频繁交替进行添加、删除操作,会使索引能力变得低下,因而要设计成批量添加或删除。通常来说,最好用IndexWriter进行删除操作,除非你确实需要通过docNum来删除文档,或者希望删除后的结果立即生效。

 

Lucene通过“黑名单”列出索引中删除的文档,换言之,文档仅仅是被标记成删除状态并存于数组中。这也意味着删除操作并不能释放磁盘空间,好在可以通过调用IndexWriter的expungeDeletes()方法释放这部分空间。更好的消息是,新版的Lucene已经不需要考虑这些了,而且expungeDeletes也被标记为Deprecated,应该会在4.0版本去掉。

 

FOR Doudou


 

你可能感兴趣的:(reader)