欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

DELETE DOCUMENT IN LUCENE luceneApache 

程序员文章站 2024-03-18 20:24:46
...
在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    =>    <docNum, freq, <pos1, pos2, ... posfreq-1> >*

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


相关标签: lucene Apache