Java 重新打开Lucene索引

Java 重新打开Lucene索引,java,lucene,Java,Lucene,我有两个独立的类-MyIndexer和mysearch。indexer类工作正常,生成一个可通过Luke浏览的索引。我看到里面有文件。我使用Lucene 4.0.0只是为了查看Luke使用的数据 我有一个JUnit测试类,有两个测试方法。第一个调用索引器并创建索引。然后关闭索引器的读取器。然后执行第二个测试方法并尝试搜索结果 我得到以下错误: org.apache.lucene.store.AlreadyClosedException: this IndexReader is closed

我有两个独立的类-
MyIndexer
mysearch
。indexer类工作正常,生成一个可通过Luke浏览的索引。我看到里面有文件。我使用Lucene 4.0.0只是为了查看Luke使用的数据

我有一个JUnit测试类,有两个测试方法。第一个调用索引器并创建索引。然后关闭索引器的读取器。然后执行第二个测试方法并尝试搜索结果

我得到以下错误:

org.apache.lucene.store.AlreadyClosedException: this IndexReader is closed
    at org.apache.lucene.index.IndexReader.ensureOpen(IndexReader.java:252)
    at org.apache.lucene.index.SegmentReader.fields(SegmentReader.java:147)
    at org.apache.lucene.index.TermContext.build(TermContext.java:90)
    at org.apache.lucene.search.TermQuery.createWeight(TermQuery.java:167)
    at org.apache.lucene.search.IndexSearcher.createNormalizedWeight(IndexSearcher.java:647)
    at org.apache.lucene.search.IndexSearcher.search(IndexSearcher.java:292)
    at com.foo.MySearcher.findArtifacts(MySearcher.java:76) // Line pointer shown in comments below
    ... (more irrelevant stacks)
MyIndexer
相关摘录:

public class MyIndexer
{

    private IndexWriter writer;

    private IndexConfiguration indexConfiguration;


    public MyIndexer()
    {
    }

    public void initialize()
            throws IOException
    {
        StandardAnalyzer analyzer = new StandardAnalyzer(indexConfiguration.getLuceneVersion());

        final File indexDir = new File(indexConfiguration.getIndexDirectory()).getCanonicalFile();
        final FSDirectory index = FSDirectory.open(indexDir);

        IndexWriterConfig config = new IndexWriterConfig(indexConfiguration.getLuceneVersion(), analyzer);

        writer = new IndexWriter(index, config);
    }

    public void addData()
            throws IOException
    {
        // ...
        // Add some data here
        // ...

        writer.addDocument(doc);
    }

    public void close()
            throws IOException
    {
        if (writer != null)
        {
            writer.commit();
            writer.close();
        }
    }

    public IndexWriter getWriter()
    {
        return writer;
    }

    public void setWriter(IndexWriter writer)
    {
        this.writer = writer;
    }

    public IndexConfiguration getIndexConfiguration()
    {
        return indexConfiguration;
    }

    public void setIndexConfiguration(IndexConfiguration indexConfiguration)
    {
        this.indexConfiguration = indexConfiguration;
    }

}
mysearch

public class MySearcher
{

    private IndexReader reader;

    private IndexSearcher searcher;

    private IndexConfiguration indexConfiguration;


    public MySearcher()
    {
    }

    public void initialize()
            throws IOException
    {
        final File indexDir = new File(indexConfiguration.getIndexDirectory()).getCanonicalFile();
        final FSDirectory index = FSDirectory.open(indexDir);

        reader = DirectoryReader.open(index);
        searcher = new IndexSearcher(reader);
    }

    // This method is currently void for the sake of testing:
    public void findData(...)
            throws IOException
    {
        int hitsPerPage = 10;

        BooleanQuery query = new BooleanQuery();
        // ...
        // Does some irrelevant query-related stuff
        // ...

        TopScoreDocCollector collector = TopScoreDocCollector.create(hitsPerPage, true);
        searcher.search(query, collector); // Place where the exception occurs.
        ScoreDoc[] hits = collector.topDocs().scoreDocs;

        System.out.println("Found " + hits.length + " hits.");
        for (int i = 0; i < hits.length; ++i)
        {
            int docId = hits[i].doc;
            Document document = searcher.doc(docId);

            System.out.println(/*... Should print out some data from each matching document's fields */);
        }

        reader.close();
    }

    public IndexReader getReader()
    {
        return reader;
    }

    public void setReader(IndexReader reader)
    {
        this.reader = reader;
    }

    public IndexSearcher getSearcher()
    {
        return searcher;
    }

    public void setSearcher(IndexSearcher searcher)
    {
        this.searcher = searcher;
    }

    public IndexConfiguration getIndexConfiguration()
    {
        return indexConfiguration;
    }

    public void setIndexConfiguration(IndexConfiguration indexConfiguration)
    {
        this.indexConfiguration = indexConfiguration;
    }

}

所以。。。这里怎么回事。。。?一旦索引器停止执行且应用程序完成,通常如何打开索引?我显然在做一些愚蠢的事情,因为我相信你以后可以重新打开索引。

你的问题在于:

searcher.initialize();
searcher.findData(...);
searcher.findData(...);
searcher.findData(...);
结合您在方法
findData
末尾调用
reader.close()
的事实。我猜对
findData
的第一个调用不会导致问题,但第二个调用会导致问题


MySearcher
的设计似乎是为了在多个搜索中保持相同的阅读器和搜索器处于打开状态(这很好)。对我来说,在搜索之后关闭阅读器是没有意义的。您只需删除对
reader.close()
的调用,就可以在findData方法中关闭读取器

Lucene的最佳实践是在完成搜索后关闭IndexSearcher,在关闭应用程序时关闭IndexWriter。对于IndexReader,这实际上取决于需要刷新索引的频率。您可以搜索近实时搜索或使用IndexReader.openIfChanged

searcher.initialize();
searcher.findData(...);
searcher.findData(...);
searcher.findData(...);