Lucene整理--索引的管理

看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();
		}
	}
}

(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自动建立的,不需要手动建立和修改。





你可能感兴趣的:(锁,Lucene,index,事物)