论坛首页 Java企业应用论坛

Lucene中关于操作索引即时生效的探讨

浏览 2013 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2009-02-14   最后修改:2009-02-17

 一、引出问题,抛砖引玉
    在Lucene中IndexWriter操作索引后,IndexReader必须重新打开索引才能使刚刚操作的数据生效。而在这个重新打开过程的一瞬间会影响整个查询的。我不知道大家在项目中是怎么去操作的,以下我将我的方法与大家分享,希望能够起到抛砖引玉的效果。


二、范例Demo

public void testLuceSynchronze() throws IOException{
	    String NAME_FIELD = "_name";
		File f = new File("log/index/testLucene");
		if(!f.isDirectory())
			f.mkdirs();
		Directory directory = FSDirectory.getDirectory(f);
		IndexWriter write = new IndexWriter(directory, false, new StandardAnalyzer());
		//写索引文件,标记为"位置一"
		Field nameField1 = new Field(NAME_FIELD,"张三",Store.YES,Index.UN_TOKENIZED);
		Field nameField2 = new Field(NAME_FIELD,"张四",Store.YES,Index.UN_TOKENIZED);
		List<Field> listFields = new ArrayList<Field>();
		listFields.add(nameField1);
		listFields.add(nameField2);
		
		for(Field field : listFields){
			Document doc = new Document();
			doc.add(field);
			write.addDocument(doc);
		}
		write.optimize();
		write.close();
		
		log.info("写索引完毕!");
	
		//以下方法构建查询Query,标记为"位置二"
		IndexSearcher searcher = new IndexSearcher(directory);
		Query tq = new PrefixQuery(new Term(NAME_FIELD,"张"));
		Hits hits = searcher.search(tq);
		if(hits.length() == 0){
			log.info("查无此人!");
		}else{
			for(int i=0;i<hits.length();i++){
				Document ret = hits.doc(i);
				String name = ret.getField(NAME_FIELD).stringValue();
				log.info(name);
			}
		}
		searcher.close();
	}

 
运行程序,控制台输入:

0    [main] INFO  test.lucene.TestSynchronize  - 写索引完毕!
78   [main] INFO  test.lucene.TestSynchronize  - 张三
78   [main] INFO  test.lucene.TestSynchronize  - 张四

以上是在位置二处构建IndexSearcher的,如果移至位置一处,就不会有查询到的记录。找到Lucene的文档,发现有这么一段说明。

 

Regardless of autoCommit, an IndexReader or IndexSearcher will only see the index as of the "point in time" that it was opened. Any changes committed to the index after the reader was opened are not visible until the reader is re-opened.

三、我的解决方案:

1)IndexWriter和IndexSearcher共用同一个Directory

2)IndexWriter或IndexReader对索引有操作的话,更改boolean的值,重新构建IndexSeacher,注意同步一下getSearcher()

	protected synchronized IndexSearcher getSearcher() {
		if(needFreshSearcher){
			this.needFreshSearcher = false;
			try {
				this.searcher.close();
				this.searcher = new IndexSearcher(getDirectory());
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		return searcher;
	}

 

 

论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics