Java 如何在不删除文档的情况下保留Lucene索引

Java 如何在不删除文档的情况下保留Lucene索引,java,lucene,indexwriter,Java,Lucene,Indexwriter,这是我关于堆栈溢出的第一个问题,祝我好运 我正在用java对Lucene索引进行分类,我需要更新一个名为category的文档字段。为此,我一直在使用Lucene 4.2和index writer updateDocument()函数,除了删除部分外,它工作得非常好。即使在更新后使用forceMergeDeletes()函数,索引也会显示一些已删除的文档。例如,如果我对包含1000个文档的索引运行分类,则索引中的最终文档数量保持不变,并按预期工作,但当我将索引文档增加到10000时,索引将显示一

这是我关于堆栈溢出的第一个问题,祝我好运

我正在用java对Lucene索引进行分类,我需要更新一个名为category的文档字段。为此,我一直在使用Lucene 4.2和index writer updateDocument()函数,除了删除部分外,它工作得非常好。即使在更新后使用forceMergeDeletes()函数,索引也会显示一些已删除的文档。例如,如果我对包含1000个文档的索引运行分类,则索引中的最终文档数量保持不变,并按预期工作,但当我将索引文档增加到10000时,索引将显示一些已删除的文档,但不是全部。那个么,我如何从索引中删除那个些已删除的文档呢

以下是我的一些代码片段:

public static void main(String[] args) throws IOException, ParseException {
    ///////////////////////Preparing config data////////////////////////////
    File indexDir = new File("/indexDir");
    Directory fsDir = FSDirectory.open(indexDir);

    IndexWriterConfig iwConf = new IndexWriterConfig(Version.LUCENE_42, new WhitespaceSpanishAnalyzer());
    iwConf.setOpenMode(IndexWriterConfig.OpenMode.APPEND);
    IndexWriter indexWriter = new IndexWriter(fsDir, iwConf);

    IndexReader reader = DirectoryReader.open(fsDir);
    IndexSearcher indexSearcher = new IndexSearcher(reader);
    KNearestNeighborClassifier classifier = new KNearestNeighborClassifier(100);
    AtomicReader ar = new SlowCompositeReaderWrapper((CompositeReader) reader);

    classifier.train(ar, "text", "category", new WhitespaceSpanishAnalyzer());

    System.out.println("***Before***");
    showIndexedDocuments(reader);
    System.out.println("***Before***");

    int maxdoc = reader.maxDoc();
    int j = 0;
    for (int i = 0; i < maxdoc; i++) {
        Document doc = reader.document(i);
        String clusterClasif = doc.get("category");
        String text = doc.get("text");
        String docid = doc.get("doc_id");
        ClassificationResult<BytesRef> result = classifier.assignClass(text);
        String classified = result.getAssignedClass().utf8ToString();

        if (!classified.isEmpty() && clusterClasif.compareTo(classified) != 0) {
            Term term = new Term("doc_id", docid);
            doc.removeField("category");
            doc.add(new StringField("category",
                    classified, Field.Store.YES));
            indexWriter.updateDocument(term,doc);
            j++;
        }
    }
    indexWriter.forceMergeDeletes(true);
    indexWriter.close();
    System.out.println("Classified documents count: " + j);        
    System.out.println();
    reader.close();

    reader = DirectoryReader.open(fsDir);
    System.out.println("Deleted docs: " + reader.numDeletedDocs());
    System.out.println("***After***");
    showIndexedDocuments(reader);
}

private static void showIndexedDocuments(IndexReader reader) throws IOException {
    int maxdoc = reader.maxDoc();
    for (int i = 0; i < maxdoc; i++) {
        Document doc = reader.document(i);
        String idDoc = doc.get("doc_id");
        String text = doc.get("text");
        String category = doc.get("category");

        System.out.println("Id Doc: " + idDoc);
        System.out.println("Category: " + category);
        System.out.println("Text: " + text);
        System.out.println();
    }
    System.out.println("Total: " + maxdoc);
}
publicstaticvoidmain(字符串[]args)抛出IOException、ParseException{
///////////////////////准备配置数据////////////////////////////
File indexDir=新文件(“/indexDir”);
目录fsDir=FSDirectory.open(indexDir);
IndexWriterConfig iwConf=new IndexWriterConfig(Version.LUCENE_42,new WhitespaceSpanishAnalyzer());
iwConf.setOpenMode(IndexWriterConfig.OpenMode.APPEND);
IndexWriter IndexWriter=新的IndexWriter(fsDir,iwConf);
IndexReader=DirectoryReader.open(fsDir);
IndexSearcher IndexSearcher=新的IndexSearcher(读卡器);
Knearestneighbor分级机=新的Knearestneighbor分级机(100);
AtomicReader ar=新的慢速复合阅读器包装器((复合阅读器)阅读器);
train(ar,“text”,“category”,新的WhitespaceSpanishAnalyzer());
System.out.println(***之前的“***”);
showIndexedDocuments(阅读器);
System.out.println(***之前的“***”);
int maxdoc=reader.maxdoc();
int j=0;
对于(int i=0;i

我花了很多时间寻找解决方案,有人说索引中删除的文档并不重要,当我们继续向索引中添加文档时,它们最终会被删除,但是我需要以一种方式来控制这个过程,我可以在任何时候迭代索引文档,并且我检索的文档实际上是活动的文档。Lucene 4.0之前的版本在IndexReader类中有一个名为isDeleted(docId)的函数,该函数给出了如果文档被标记为已删除,这可能只是我问题解决方案的一半,但我还没有找到在Lucene 4.2版本中实现这一点的方法。如果你知道如何做到这一点,我真的很感谢你分享它。

你可以检查是一个文档被删除是类,如:

Bits liveDocs = MultiFields.getLiveDocs(reader);
if (!liveDocs.get(docID)) ...
因此,将其应用到代码中,可能类似于:

int maxdoc = reader.maxDoc();
Bits liveDocs = MultiFields.getLiveDocs(reader);
for (int i = 0; i < maxdoc; i++) {
    if (!liveDocs.get(docID)) continue;
    Document doc = reader.document(i);
    String idDoc = doc.get("doc_id");
    ....
}
int-maxdoc=reader.maxdoc();
Bits liveDocs=MultiFields.getLiveDocs(读卡器);
对于(int i=0;i

顺便说一下,听起来您以前使用过3.X,现在使用的是4.X。对于理解版本之间的此类更改以及如何解决这些更改非常有帮助。

谢谢您的回答。Lucene迁移指南也非常有用,我会一直关注它。