DELETE DOCUMENT IN LUCENE

阅读更多
在Luecne中,没有方法对已经被索引的Document进行更新,唯一的办法就是讲原有的Document对象删除,然后写入一个新的Document。

在IndexReader中提供了两个方法来删除Document :

public final void  deleteDocument(int docNum) throws IOException

public final int deleteDocuments(Term term) throws IOException

(注:在1.4的Lucene中分别为delete(int docNum)和delete(Term term)

对于一个document被删除之后,它只是在TermDocs 或者TermPositions enumerations 中不会被出现,但是并没有真正的被删除,这个时候试图用方法document(int)方法读取document的field就会出错,但是The presence of this document may still be reflected in the docFreq(org.apache.lucene.index.Term) statistic, though this will be corrected eventually as the index is further modified.       

但是这个方法在实际的应用中就显得麻烦,因为你很难知道一个document的docNum,从而就不能用这个方法去删除document。

这个时候就会选择第二个方法,它会删除包含term的所有的document,要使的这个方法每次只删除一个document,简单的做法就是在document的中加一个有着唯一的ID的field,那么在删除这个document的时候就用这个方法deleteDocuments(new Term("xx_ID",xx.getID()); 这样就可以删除对应的document,然后加进去新的document。

但是在写代码的过程中我还是遇到了没有办法删除document对象的状况。在确定不是参数有问题的情况下,我的第一反应是,对同一个索引打开了一个IndexWriter和一个IndexReader,在IndexReader删除的时候,IndexWriter还没有关闭,我怀疑有写锁的存在(PS:关于Lucene的线程安全性还没有仔细看呢),但是独立写了个测试,发现这不是问题的所在。

我用 deleteDocument(int docNum) 确成功的删除了document,那么是什么导致deleteDocuments(Term term)没有办法删除呢??

仔细检查了一下,发现1.4版本中的示例代码中是这样的

doc.add(Field.Text("name","Word1 word2 word3"));

reader.delete(new Term("name","word1"));

而我的代码中是doc.add(new Field("xx_ID",xx.getID(),Field.Store.YES,Field.Index.NO));

而在1.4中Field.Text()是将字段切词,索引,存储的

!!!!!!!!!所以我将代码改为Field.Index.UN_TOKENIZD再测试就没有问题了,顺利将document删除了。分析原因,把lucene的源代码下了下来,没看之前的想法是,它要删除包含这个term的document可能调用类似search的方法,而我没有将这个ID的field索引打开,可能就导致搜索不到这个document。(PS:只是乱想)

源代码还是很烦,不是一下就能看明白,以后再说~~~~

有一个简单的认识:

termDocs()实现的是Term    =>    >*

这样一个映射,也许这两个删除的方法都是由protected abstract void doDelete(int docNum) throws IOException 这个方法真正实现的(PS:猜测而已),也许问题的入口就在如何构建到这个映射关系的,看了代码之后再慢慢想。


你可能感兴趣的:(lucene,Apache)