看lucene主页(http://lucene.apache.org/)上目前lucene已经到4.9.0版本了, 参考学习的书是按照2.1版本讲解的,写的代码例子是用的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();
}
}
}
(2)、读取索引文档相关的基本信息,读取文档中的字段
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自动建立的,不需要手动建立和修改。