[原]Lucene系列-近实时搜索
- - 文武天下近实时搜索(near-real-time)可以搜索IndexWriter还未commit的内容,介于immediate和eventual之间,在数据比较大、更新较频繁的情况下使用. lucene的nrt可以控制更新生效的间隔时间. 从indexwriter中获得indexreader. 建立indexsearcher.
近实时搜索(near-real-time)可以搜索IndexWriter还未commit的内容,介于immediate和eventual之间,在数据比较大、更新较频繁的情况下使用。lucene的nrt可以控制更新生效的间隔时间。
基本过程:
需要用到DirectoryReader.openIfChanged函数,该函数会对老readers做删除、合并,将变化应用到新reader中。代码如下,基于lucene 4.10。
private Directory ramDir = new RAMDirectory(); public void testNrt() throws IOException { //IndexWriter IndexWriterConfig writerConfig = new IndexWriterConfig(Version.LUCENE_4_10_0, new StandardAnalyzer()); IndexWriter writer = new IndexWriter(ramDir, writerConfig); Document doc = new Document(); doc.add(new TextField("title", "lucene", Field.Store.YES)); doc.add(new TextField("author", "zhangsan", Field.Store.YES)); writer.addDocument(doc); //IndexReader,基于IndexWriter打开的IndexReader <strong>IndexReader reader = DirectoryReader.open(writer, true);</strong> IndexSearcher searcher = new IndexSearcher(reader); TermQuery query = new TermQuery(new Term("title", "lucene")); TopDocs docs = searcher.search(query, 10); System.out.println(docs.totalHits); for (int i = 0; i < 10; ++i) { doc = new Document(); doc.add(new TextField("title", "lucene " + i, Field.Store.YES)); doc.add(new TextField("author", "zhangsan " + i, Field.Store.YES)); writer.addDocument(doc); } //openIfChanged,如果有提交或未提交的变化,就打开新的indexreader。 <strong>IndexReader newReader = DirectoryReader.openIfChanged((DirectoryReader) reader, writer, true);</strong> if (reader != newReader) { searcher = new IndexSearcher(newReader); reader.close(); } docs = searcher.search(query, 10); System.out.println(docs.totalHits); }
在实际应用中,会并行的进行搜索、建索引、打开新Reader,需要考虑多线程安全问题。lucene提供了SearcherManager extends ReferenceManager<IndexSearcher>来确保searcher和索引的使用安全。
private Directory ramDir = new RAMDirectory(); public void testNrt() throws IOException { //IndexWriter IndexWriterConfig writerConfig = new IndexWriterConfig(Version.LUCENE_4_10_0, new StandardAnalyzer()); IndexWriter writer = new IndexWriter(ramDir, writerConfig); Document doc = new Document(); doc.add(new TextField("title", "lucene", Field.Store.YES)); doc.add(new TextField("author", "zhangsan", Field.Store.YES)); writer.addDocument(doc); //可以自定义SearcherFactory来对生成的IndexSearcher进行设置,如setSimilarity <strong>SearcherManager searcherManager = new SearcherManager(writer, true, new SearcherFactory());</strong> //获取当前Searcher <strong>IndexSearcher searcher = searcherManager.acquire();</strong> TermQuery query = new TermQuery(new Term("title", "lucene")); TopDocs docs = searcher.search(query, 10); System.out.println(docs.totalHits); //减少该searcher的引用,本质是利用了IndexReader的refCount,当refCount为0时关闭reader <strong>searcherManager.release(searcher);</strong> for (int i = 0; i < 10; ++i) { doc = new Document(); doc.add(new TextField("title", "lucene " + i, Field.Store.YES)); doc.add(new TextField("author", "zhangsan " + i, Field.Store.YES)); writer.addDocument(doc); } //调用DirectoryReader.openIfChanged获取新searcher searcherManager.maybeRefresh(); searcher = searcherManager.acquire(); docs = searcher.search(query, 10); System.out.println(docs.totalHits); searcherManager.release(searcher); //释放资源 <strong>searcherManager.close();</strong>