近实时搜索就是他能打开一个IndexWriter快速搜索索引变更的内容,而不必关闭writer,或者向writer提交,这个功能是在2.9版本以后引入的,在以前没有这个功能时,必须调用writer的commit方法,然后重新打开reader,这个过程很耗费时间,因为writer的提交必须对索引里的所有新文件进行同步,同步操作耗费系统资源,近实时搜索使我们能够对新创建还未提交的索引进行搜索。
在4.5的版本上做一个简单的测试示例,参考lucene in action
import junit.framework.TestCase;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.FieldType;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.*;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.RAMDirectory;
import org.apache.lucene.util.Version;
public class NearRealTimeTest extends TestCase {
public void testNearRealTime() throws Exception {
Directory dir = new RAMDirectory();
IndexWriterConfig config = new IndexWriterConfig(Version.LUCENE_45,new StandardAnalyzer(Version.LUCENE_45));
IndexWriter writer = new IndexWriter(dir, config);
FieldType fieldType = new FieldType();
fieldType.setIndexed(false);//set 是否索引
fieldType.setStored(false);//set 是否存储
fieldType.setTokenized(true);//set 是否分类
fieldType.setOmitNorms(false);
for(int i=0;i<10;i++) {
Document doc = new Document();
doc.add(new Field("id", ""+i, fieldType));
doc.add(new Field("test", "aaa", TextField.TYPE_NOT_STORED));
writer.addDocument(doc);
}
//IndexReader reader = writer.getReader(); // 老版本的 3.x
DirectoryReader reader = DirectoryReader.open(writer,true); //创建近实时reader
IndexSearcher searcher = new IndexSearcher(reader); //将reader封装在IndexSearcher
Query query = new TermQuery(new Term("test", "aaa"));
TopDocs docs = searcher.search(query, 1);
assertEquals(10, docs.totalHits); // 返回10个搜索结果
writer.deleteDocuments(new Term("id", "7")); // 删除一个文档
Document doc = new Document();
doc.add(new Field("id", "11", fieldType));
doc.add(new Field("test", "bbb", TextField.TYPE_NOT_STORED));
writer.addDocument(doc);
//IndexReader newReader = reader.reopen(); //老版本3.x
IndexReader newReader = DirectoryReader.openIfChanged(reader,writer,true); //重启reader
reader.close();
assertFalse(reader == newReader);
reader.close();
searcher = new IndexSearcher(newReader);
TopDocs hits = searcher.search(query, 10);
assertEquals(9, hits.totalHits);
query = new TermQuery(new Term("text", "bbb"));
hits = searcher.search(query, 1);
assertEquals(1, hits.totalHits);
newReader.close();
writer.close();
}
}
可以看到更新文档后用 DirctoryReader.openIfChanged来获取Reader,如果有新内容,则返回新的Reader,这时我们需要关闭老的Reader。
最后测试通过