2013-07-12 99 views
1

我是Lucene的新手,请耐心等待。重新打开Lucene索引

我有两个单独的类 - MyIndexerMySearcher。索引器类工作正常,并产生一个可与卢克一起浏览的索引。我看到了它的文档。我正在使用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; 
    } 

} 

MySearcher

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; 
    } 

} 

MyLuceneTest:

public class MyLuceneTest 
{ 

    public static final String INDEX_DIR = "target/test-indexes/index-001"; 

    private static IndexConfiguration configuration; 


    @Before 
    public void setUp() 
      throws Exception 
    { 
     configuration = new IndexConfiguration(); 
     configuration.setIndexDirectory(INDEX_DIR); 
    } 

    @Test 
    public void testVerboseIndexing() 
      throws IOException 
    { 
     MyIndexer indexer = new MyIndexer(); 
     indexer.setIndexConfiguration(configuration); 
     indexer.initialize(); 

     // Adding some data here 
     ... 
     indexer.addData(...); 
     ... 

     indexer.close(); 

     // Obviously, we're not doing any assertions right now. 
    } 

    @Test 
    public void testSearch() 
      throws IOException 
    { 
     MySearcher searcher = new MySearcher(); 
     searcher.setIndexConfiguration(configuration); 
     searcher.initialize(); 

     searcher.findData(...); 

     searcher.findData(...); 

     searcher.findData(...); 

     // Obviously, we're not doing any assertions right now. 
    } 

} 

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

非常感谢提前! :)

回答

2

你的问题就在这里:

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

的事实,你是在方法findData结束通话reader.close()结合。我猜想第一次拨打电话findData不会导致问题,但第二个电话会。

MySearcher似乎被设计为保持相同的阅读器和搜索器在多个搜索中打开(这很好)。在搜索之后关闭读者对我来说没有任何意义。您应该简单地删除该电话reader.close()

+0

绝对的辉煌!我知道我在做一些愚蠢的事情!我的感谢! :) – carlspring

1

您正在使用findData方法关闭阅读器。

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

+0

+1:谢谢,我想,编写代码时没有引起足够的重视。 – carlspring