Lucene索引删除详解

2012-04-27

 如下索引,NameCount读出来是2,说明新的段位_2.xxx,_2.yyy

lucene索引 段

  SegCount

    段(Segment)的个数。

    如上图,此值为2。

  SegCount元数据信息:

     SegName

        段名,所有属于同一个段的文件都有以段名作为文件名。

        如上图:第一个段的段名为“_0”,第二个段的段名为“_1”。

   SegSize

        此段中包含的文档数

        然而此文档数是包括已经删除,又没有optimize的文档的,因为在optimize之前,Lucene的段中包含了所有被索引过的文档,而被删除的文档是保存在.del文件中的,在搜索过程中,是先从段中读到了被删除的文档,然后再用.del中的标志,将这篇文档过滤掉。

       如下的代码形成了上图的索引,可以看出索引了两篇文档形成了_0段,然后又删除了其中一篇,形成了_0_1.del,又索引了两篇文档形成_1段,然后又删除了其中一篇,形成了_1_1.del。因而在两个段中,此值都是2。

IndexWriter writer = new IndexWrite(FSDirectory.open(INDEX_DIR),

                                                    new StandardAnalyzer(Version.LUCENE_CURRENT),

                                                    true,

                                                    IndexWriter.MaxFieldLength.LIMITED);

writer.setUseCompoundFile(false);

indexDocs(writer,docDir);//docDir中只有两篇文档

 //文档一位:Students should be allowed to go out with their friends,but not allowed  to drink beer 

//文档二:my friend jerry went to school to see his students but not found them drunk which is not allowed.

writer.commit();//提交两篇文档,形成_0段。

writer.deleteDocuments(new Term("contents","school"));//删除文档二

writer.commit();//提交删除,形成_0_1.del

indexDocs(writer,docDir);//再次索引两篇文档,Lucene不能判别文档与文档的不同,因而算两篇新的文档。

writer.commit();//提交两篇文档,形成_1段

writer.deleteDocuments(new Term("contents","school"));// 删除第二次添加的文档二

writer.close();//提交删除,形成_1_1.del

 

。DelGen

     1、.del文件的版本号

     2、lucene中,在optimize之前,删除的文档是保存在.del文件中的。

     3、在lucene2.9中,文档删除有以下几种方式:

          IndexReader.deleteDocument(int docID)是用IndexReader 按文档号删除。

          IndexReader.deleteDocuments(Term term)是用IndexReader删除包含此词(Term)的文档。

          IndexWriter.deleteDocuments(Term term)是用IndexWriter删除包含此词(Term)的文档。

          IndexWriter.deleteDocuments(Term[] terms)IndexWriter批量删除文档。

          IndexWriter.deleteDocuments(Query query)删除满足query查询的文档。

          IndexWriter.deleteDocuments(Query[] queries)删除满足多个查询数组的文档。

      原来的版本中Lucene的删除一直是由IndexReader来完成的,在Lucene2.9中虽可以用IndexWriter来删除,但是其真实的实现是在IndexWriter中保存了readerpool,当IndexWriter向索引文件提交删除的时候,仍然是从readerpool中得到相应的IndexReader,并用IndexReader来进行删除的,下面的代码可以说明:

IndexWriter.applyDeletes()

  ->DocumentsWriter.applyDeletes(SegmentInfos)

       ->reader.deleteDocument(doc);

//DelGen是每当IndexWriter向索引文件提交删除操作的时候,加1,并生成新的.del文件。

IndexWriter.commit()

 ->IndexWriter.applyDeletes()

    ->IndexWriter$ReaderPool.release(SegmentReader)

      ->SegmentReader(IndexReader).commit()

        ->SegmentReader.doCommit(Map)

           ->SegmentInfo.advanceDeGen()

            ->if(delGen==NO){

                  delGen=YES;  

             }else{

                delGen++;

            }

IndexWriter writer=new IndexWriter(FSDirectory.open(INDEX_DIR),new StandardAnalyzer(Version.LUCENE_CURRENT),true,IndexWriter.MaxFieldLenth.LIMITED);

writer.setUseCompoundFile(false);

indexDoc(writer,docDir); //索引两篇文档,一篇包含"school",另一篇包含"beer"

writer.commit();//提交两篇文档到索引文件,形成段(Segment)"_0"
writer.deleteDocuments(new Term("contents", "school"));//删除包含"school"的文档,其实是
删除了两篇文档中的一篇。
writer.commit();//提交删除到索引文件,形成"_0_1.del"
writer.deleteDocuments(new Term("contents", "beer"));//删除包含"beer"的文档,其实是删
除了两篇文档中的另一篇。
writer.commit();//提交删除到索引文件,形成"_0_2.del"
indexDocs(writer, docDir);//索引两篇文档,和上次的文档相同,但是Lucene无法区分,认为是
另外两篇文档。
writer.commit();//提交两篇文档到索引文件,形成段"_1"
writer.deleteDocuments(new Term("contents", "beer"));//删除包含"beer"的文档,其中段"_0"已经无可删除,段"_1"被删除一篇。writer.close();//提交删除到索引文件,形成"_1_1.del"
形成索引文件如下:
 

作者:robotbird, 分类:关于代码 标签: lucene , 浏览(10553), 评论(0)
上一篇: 关于蛋生鸡鸡生蛋的问题
下一篇: 罗马的故事-苏拉

相关文章

(0)条评论 订阅

发表评论

电子邮件用于回复通知和avatar全球唯一头像 *

*