Lucene笔记04-Lucene索引的删除与更新

一、删除索引

public void delete() {
    IndexWriter indexWriter = null;
    try {
        indexWriter = new IndexWriter(directory, new IndexWriterConfig(Version.LUCENE_35, new StandardAnalyzer(Version.LUCENE_35)));
        // 参数是一个选项,可以是一个Query(查找的一个范围),也可以是一个Term(一个精确的查找值)
        // 此时文档没有被彻底删除,只是放在了回收站中
        indexWriter.deleteDocuments(new Term("id", "1"));
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if (indexWriter != null) {
            try {
                indexWriter.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

public void query() {
    try {
        IndexReader indexReader = IndexReader.open(directory);
        // numDocs()返回索引中未被删除的文档总数
        // maxDoc()返回索引中删除(标记为删除,但是还没有真正删除)和未被删除的文档总数
        // numDeleteDocs()返回被放在回收站的索引的数目,这些是可以恢复的
        System.out.println("numDocs=" + indexReader.numDocs());
        System.out.println("maxDocs=" + indexReader.maxDoc());
        System.out.println("numDeleteDocs=" + indexReader.numDeletedDocs());
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if(indexReader!=null){
            try {
                indexReader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

这里的删除并没有完全删除,而是放在了“回收站”,通过query方法可以看到,maxDocs不等于numDocs的,并且numDeleteDocs的值就是刚刚被删除的数目,被删除的这个索引是可以恢复的。

二、恢复被删除的索引

public void undelete() {
    // 使用IndexReader来恢复
    try {
        // IndexReader默认是用来读索引的,现在要用IndexReader来写(恢复)索引,需要添加一个参数readOnly,默认情况是true,我们需要指定成false
        IndexReader indexReader = IndexReader.open(directory, false);
        indexReader.undeleteAll();
        indexReader.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

public void query() {
    try {
        IndexReader indexReader = IndexReader.open(directory);
        // numDocs()返回索引中未被删除的文档总数
        // maxDoc()返回索引中删除(标记为删除,但是还没有真正删除)和未被删除的文档总数
        // numDeleteDocs()返回被放在回收站的索引的数目,这些是可以恢复的
        System.out.println("numDocs=" + indexReader.numDocs());
        System.out.println("maxDocs=" + indexReader.maxDoc());
        System.out.println("numDeleteDocs=" + indexReader.numDeletedDocs());
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if(indexReader!=null){
            try {
                indexReader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

使用IndexReader来进行恢复,需要多指定一个readOnly参数,否则会报错。undelete()之后,再去执行query(),就可以发现被删除的索引恢复了。

三、强制删除索引(不经过回收站,无法恢复)

public void forceDelete() {
    IndexWriter indexWriter = null;
    try {
        indexWriter = new IndexWriter(directory, new IndexWriterConfig(Version.LUCENE_35, new StandardAnalyzer(Version.LUCENE_35)));
        indexWriter.forceMergeDeletes();
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if (indexWriter != null) {
            try {
                indexWriter.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

public void query() {
    try {
        IndexReader indexReader = IndexReader.open(directory);
        // numDocs()返回索引中未被删除的文档总数
        // maxDoc()返回索引中删除(标记为删除,但是还没有真正删除)和未被删除的文档总数
        // numDeleteDocs()返回被放在回收站的索引的数目,这些是可以恢复的
        System.out.println("numDocs=" + indexReader.numDocs());
        System.out.println("maxDocs=" + indexReader.maxDoc());
        System.out.println("numDeleteDocs=" + indexReader.numDeletedDocs());
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if(indexReader!=null){
            try {
                indexReader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

先执行delete(),再执行forceDelete(),再次查询发现numDeleteDocs是0,numDocs和maxDocs都比前面少1,意味着回收站中的索引彻底被删除了 。

四、手动合并

public void merge() {
    IndexWriter indexWriter = null;
    try {
        indexWriter = new IndexWriter(directory, new IndexWriterConfig(Version.LUCENE_35, new StandardAnalyzer(Version.LUCENE_35)));
        // 会将索引合并为两段,这两段中被删除的数据会被清空
        // 在Lucene3.5之后不建议使用,因为会浪费大量的开销,Lucene会根据情况自动处理
        indexWriter.forceMerge(2);
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if (indexWriter != null) {
            try {
                indexWriter.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

不建议使用,因为会损耗比较大的性能,这里就不过多研究了。

五、更新索引

public void update() {
    IndexWriter indexWriter = null;
    try {
        indexWriter = new IndexWriter(directory, new IndexWriterConfig(Version.LUCENE_35, new StandardAnalyzer(Version.LUCENE_35)));
        // Lucene的更新其实是先删除后添加
        Document document = new Document();
        document.add(new Field("id", "11", Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS));
        document.add(new Field("email", emails[0], Field.Store.YES, Field.Index.NOT_ANALYZED));
        document.add(new Field("content", contents[0], Field.Store.NO, Field.Index.ANALYZED));
        document.add(new Field("name", names[0], Field.Store.YES, Field.Index.NOT_ANALYZED_NO_NORMS));
        indexWriter.updateDocument(new Term("id", "1"), document);
    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if (indexWriter != null) {
            try {
                indexWriter.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

Lucene中的更新分为两步进行:先删除,后添加,通过上面的例子可以看出来,更新id为1的文档,更新后的文档id也可以发生变化,所以说是先删除,后添加。为了进一步验证,可以执行query()方法,会发现numDeleteDocs是1,也就是发生了删除操作,再一次证实了这个观点。

你可能感兴趣的:(Lucene)