2016-02-29 37 views
0

我需要在Lucene中添加文檔後立即使用我的結果。我讀的所有內容都說我應該緩存IndexSearcher實例,但是我沒有看到如何在每次寫入時重新打開IndexReader並因此IndexSearcher無法實現我想要的內容...Lucene NRT - 每次提交後都打開一個新的IndexReader?

我在做什麼錯了?

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

這些告誡的意義在於,您不用爲每個查詢*打開一個新的'IndexReader'。編寫完成後,您需要重新打開以進行更改。創建一個新的IndexSearcher並不是特別昂貴。它打開了價格昂貴的'IndexReader'。 – femtoRgon

+0

@femtoRgon我想,爲了滿足我的要求,我必須在添加每個文檔後打開一個'IndexReader'。 – Cheetah

+0

你有一個選項,可能對性能有幫助,你可以使用['openIfChanged(DirectoryReader oldReader,IndexWriter writer,boolean applyAllDeletes)'](https://lucene.apache.org/core/5_4_0/core/org /apache/lucene/index/DirectoryReader.html#openIfChanged(org.apache.lucene.index.DirectoryReader,%20org.apache.lucene.index.IndexWriter,%20boolean)),它允許您搜索未提交的更改(即沒有關閉或委託作者)。 – femtoRgon

回答

0

Lucene不是爲提供實時搜索結果而設計的。所以如果這真的是一個要求,你應該看看別的東西。

但是Lucene可以提供附近的實時搜索結果,所以你的用戶將不得不等待, 1秒鐘之後,更改纔可搜索。做到這一點的方法是使用SearcherManager(http://lucene.apache.org/core/5_5_0/core/org/apache/lucene/search/SearcherManager.html),並有一個後臺線程定期刷新當前的索引閱讀器。

相關問題