看lucene主页(http://lucene.apache.org/)上目前lucene已经到4.9.0版本了, 参考学习的书是按照2.1版本讲解的,写的代码例子是用的3.0.2版本的,版本
的不同导致有些方法的使用差异,但是大体还是相同的。
源代码用到的jar包(3.0.2版本)下载地址
参考资料:
1、公司内部培训资料
2、《Lucene搜索引擎开发权威经典》于天恩著.
Lucene使用挺简单的,耐心看完都能学会,还有源代码。
昨天建立了一个简单的索引,今天总结下怎么查看索引、更新索引和删除索引。
一、查看索引的信息
查看索引大体有三种方法:
1、使用IndexWriter类读取索引的相关信息
使用IndexWriter类可以得到索引的一些相关信息:
获取索引的目录信息:IndexWriter.getDirectory().toString();
获取索引的分析器:IndexWriter.getAnalyzer().toString();
总之是通过IndexWriter的相关方法获取索引的相关信息,具体可以查阅API文档。
2、使用IndexReader及其子类获取索引的相关信息
注意:例子当中没有创建索引,用到的索引是上文创建的
(1)、通过IndexReader类获取索引的基本信息
import java.io.File; import java.io.IOException; import java.util.Date; import org.apache.lucene.index.CorruptIndexException; import org.apache.lucene.index.IndexReader; import org.apache.lucene.store.Directory; import org.apache.lucene.store.SimpleFSDirectory; public class LuceneIndexReaderTest1 { public static void main(String[] args) { File indexDir = new File("E:\\Index"); try { Directory dir = new SimpleFSDirectory(indexDir); IndexReader ir= IndexReader.open(dir); //indexExists()方法 判断索引是否存在 if(ir.indexExists(dir)){ System.out.println("该索引存在!!"); }else{ System.out.println("该索引不存在!!"); } //lastModified()方法 返回指定目录上的索引上次修改的时间(毫秒形式) Date d=new Date(ir.lastModified(dir)); System.out.println(d); //isOptimized() 检查指标是否是最佳的 System.out.println(ir.isOptimized()); //directory() 获得索引目录 System.out.println(ir.directory()); //numDocs() 索引中文档数量 System.out.println(ir.numDocs()); // maxDoc() 返回索引可用的最大索引ID System.out.println(ir.maxDoc()); //close()关闭 ir.close(); } catch (CorruptIndexException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
import java.io.File; import java.io.IOException; import java.util.Date; import org.apache.lucene.document.Document; import org.apache.lucene.document.Field; import org.apache.lucene.index.CorruptIndexException; import org.apache.lucene.index.IndexReader; import org.apache.lucene.store.Directory; import org.apache.lucene.store.SimpleFSDirectory; public class LuceneIndexReaderTest2 { public static void main(String[] args) { File indexDir = new File("E:\\Index"); try { Directory dir = new SimpleFSDirectory(indexDir); IndexReader ir= IndexReader.open(dir); int num=ir.numDocs(); System.out.println(num); System.out.println("--------------------------------"); //Document相关信息 Document doc=ir.document(5);//5代表document的索引ID System.out.println(doc); System.out.println("--------------------------------"); for(int i=0 ; i<num; i++){ doc=ir.document(i); Field field=doc.getField("bookname");//获取每个doc中的field System.out.println(field.stringValue());//输出字段的值 System.out.println("--------------------------------"); } } catch (CorruptIndexException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
二、删除索引中的文档
如果文档中某个索引不需要被检索了,那么应该从索引中将该文档删除。在Lucene中通过IndexReader和indexModifier两个类从索引中删除文档。
1、使用IndexReader删除
IndexReader删除文档需要根据文档的序号进行删除
import java.io.File; import java.io.IOException; import org.apache.lucene.document.Document; import org.apache.lucene.document.Field; import org.apache.lucene.index.CorruptIndexException; import org.apache.lucene.index.IndexReader; import org.apache.lucene.store.Directory; import org.apache.lucene.store.SimpleFSDirectory; public class deleteIndex1 { public static void main(String[] args) { File indexDir = new File("E:\\Index"); try { Directory dir = new SimpleFSDirectory(indexDir); IndexReader ir= IndexReader.open(dir,false);//第二个参数设置的是否只读,默认是true ir.deleteDocument(8); System.out.println(ir.numDeletedDocs()); //判断是否删除成功 ir.close();//删除后要关闭,否则删除无效 } catch (CorruptIndexException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } }这个时候,文档并没有被真正删除,只是做了已经被删除的标记,从而使之不能参与检索,通过调用undeleteAll()方法可以将删除的文档都恢复过来。
使用IndexWriter的optimize()方法可以对做了删除标记的索引进行物理删除,都很简单,不举例。
使用IndexReader.deleteDocuments(new Term("bookname","女"))可以按照词条批量删除索引,不举例
三、更新索引中的文档
无非先删除再添加而已
四、索引的同步
1、lucene并发访问规则:
lucene是被设计用于web环境的,所建立的搜索引擎会不止被一个线程访问,因此需要考虑了并发访问的问题,并发访问的问题如果处理不好会导致索引文件的损坏,为了避免
类似问题,需要谨记以下规则:
1)、任意数量的只读操作都可以同时进行
2)、在某一时刻,只允许一个修改索引的操作。也就是说在同一时间一个索引只能被一个IndexWriter或者IndexReader对象打开。
3)、只读操作可以在索引被修改的情况下进行,并且也可以是并发只读。
2、索引锁机制
为了处理索引同步的问题,Lucene内置了一种锁机制。锁,体现为一种文件。
锁有两种:write.lock 和 commit.lock .
write.lock用于阻止进程同时修改一个索引。对于IndexWriter和IndexReader两个类,在他们进行索引的添加、修改和删除操作的时候,write.lock文件就产生了。这时候如果
有人想修改索引是做不到的。必须要等到close()之后才可以。这两个类调用close()后索文件write.lock也就消失了。
在读取和合并索引块的时候,会用到commit.lock锁,这是一个事物锁。例如,在优化索引的时候,需要先将所有的索引块合并起来,等合并成功之时,再将原先分散的索引块
删除,整个过程任何一步出现问题都会导致索引优化失败,因此要用到事物锁。
这两种锁都是操作索引Lucene自动建立的,不需要手动建立和修改。