Lucene NRT - 每次提交后都会打开一个新的IndexReader?

时间:2016-02-29 15:45:35

标签: java lucene

我需要在添加文档后立即使用Lucene中的结果。我读到的所有内容都说我应该缓存IndexSearcher实例,但是如果没有在每次写入时重新打开IndexReader,我也不会看到如何实现我想要的,因此也是IndexSearcher ...

我做错了什么?

class LuceneStorage {

    private final Directory luceneDirectory;
    private final IndexWriter indexWriter;

    private volatile DirectoryReader indexReader;

    LuceneStorage() {
        try {
            this.luceneDirectory = NIOFSDirectory.open(Paths.get(System.getProperty("user.home")).resolve("lucene"));

            IndexWriterConfig config = new IndexWriterConfig(new KeywordAnalyzer());
            config.setOpenMode(IndexWriterConfig.OpenMode.CREATE_OR_APPEND);

            this.indexWriter = new IndexWriter(luceneDirectory, config);
            this.indexReader = DirectoryReader.open(indexWriter);
        } catch (IOException e) {
            throw new UncheckedIOException(e);
        }
    }

    public Stream<String> read(String id) {
        IndexSearcher indexSearcher = new IndexSearcher(indexReader);
        QueryParser queryParser = new QueryParser("id", new KeywordAnalyzer());
        StreamableSimpleCollector collector = new StreamableSimpleCollector();

        try {
            indexSearcher.search(queryParser.parse(id), collector);
        } catch (Exception e) {
            throw new IllegalStateException(e);
        }

        IntStream docIds = collector.stream();

        return docIds.mapToObj(i -> {
                try {
                    return indexSearcher.doc(i).get("content");
                } catch (IOException e) {
                    throw new UncheckedIOException(e);
                }
            });
    }

    public String write(String content, String... ids) {
        String uuid = UUID.randomUUID().toString();

        Document document = new Document();
        document.add(new StringField("id", uuid, Field.Store.YES));

        Stream.of(ids)
            .forEach(i -> document.add(new StringField("id", i, Field.Store.YES)));

        document.add(new StoredField("content", content));

        try {
            indexWriter.addDocument(document);
            indexReader = DirectoryReader.openIfChanged(indexReader);
        } catch (IOException e) {
            throw new UncheckedIOException(e);
        }

        return uuid;
    }
}

1 个答案:

答案 0 :(得分:0)

Lucene并非旨在提供实时搜索结果。因此,如果这确实是一项要求,那么你应该看看别的东西。

然而,Lucene可以提供实时搜索结果,因此您的用户最多必须等待,例如。在更改之前1秒可搜索。这样做的方法是使用SearcherManager(http://lucene.apache.org/core/5_5_0/core/org/apache/lucene/search/SearcherManager.html)并有一个后台线程,定期刷新当前的索引读取器。