Java小强个人技术博客站点    手机版
当前位置: 首页 >> 框架 >> Lucene入门之增删改查

Lucene入门之增删改查

80812 框架 | 2016-3-15

Lucene是apache软件基金会4 jakarta项目组的一个子项目,是一个开放源代码的全文检索引擎工具包,即它不是一个完整的全文检索引擎,而是一个全文检索引擎的架构,提供了完整的查询引擎和索引引擎,部分文本分析引擎(英文与德文两种西方语言)。Lucene的目的是为软件开发人员提供一个简单易用的工具包,以方便的在目标系统中实现全文检索的功能,或者是以此为基础建立起完整的全文检索引擎。


Lucene入门之增删改查


本示例实用junit来测试,使用了3.5.0版本,实用Maven来引入,POM文件:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<groupId>com.javacui.lucene</groupId>
	<artifactId>zlucene</artifactId>
	<version>1.0</version>
	<packaging>jar</packaging>
	<name>zlucene</name>
	<url>http://maven.apache.org</url>
	<properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
	</properties>
	<dependencies>
		<dependency>
			<groupId>junit</groupId>
			<artifactId>junit</artifactId>
			<version>4.7</version>
		</dependency>
		<dependency>
			<groupId>org.apache.lucene</groupId>
			<artifactId>lucene-core</artifactId>
			<version>3.5.0</version>
		</dependency>
		<dependency>
			<groupId>org.apache.lucene</groupId>
			<artifactId>lucene-analyzers</artifactId>
			<version>3.5.0</version>
		</dependency>
		<dependency>
			<groupId>org.apache.lucene</groupId>
			<artifactId>lucene-highlighter</artifactId>
			<version>3.5.0</version>
		</dependency>
		<dependency>
			<groupId>log4j</groupId>
			<artifactId>log4j</artifactId>
			<version>1.2.17</version>
		</dependency>
	</dependencies>
</project>


建立索引的步骤

1.创建Directory

2.创建IndexWriter

3.创建Document对象

4.为Document添加Field

Directory是存放索引的位置,是一个公用的对象,所以写在初始化里面。

private static Directory directory = null;
@Before
public void init() throws Exception {
	directory = FSDirectory.open(new File("D:/tmp/lucene"));
}

如果是在内存中创建,实用以下代码:

Directory directory = new RAMDirectory();

然后编写添加索引的代码

@Test
public void createIndex() throws Exception {
	IndexWriterConfig iwc = new IndexWriterConfig(Version.LUCENE_35, new StandardAnalyzer(Version.LUCENE_35));
	IndexWriter writer = null;
	writer = new IndexWriter(directory, iwc);
	Document doc = null;
	File f = new File("D:/data/test");
	for(File file : f.listFiles()){
		doc = new Document();
		doc.add(new Field("context", new FileReader(file)));
		doc.add(new Field("fileName",file.getName(),Field.Store.YES,Field.Index.NOT_ANALYZED));
		doc.add(new Field("filePath",file.getPath(),Field.Store.YES,Field.Index.NOT_ANALYZED));
		writer.addDocument(doc);
	}
	writer.close();
	log.debug("运行结束");
}

这里D:/data/test文件夹下有很多log日志文件,遍历这个目录,把文件的名称、路径,和内容放到Lucene中。

文档Document和域Field的关系

文档Document相当于关系表中的每一条记录,域相当于表中的每一个字段,先创建文档,之后为文档添加域.

域存储选项和域索引选项,均需要在域添加的时候设置

存储域选项

Field.Store.YES表示把这个域中的内容完全存储到文件中,方便进行文本的还原

Field.Store.NO表示把这个域中的内容不存储到文件中,但是可以被索引,此时内容无法还原(即无法document.get());

索引域选项

Field.Index.ANALYZED:进行分词和索引,适用于标题和内容等

Field.Index.NOT_ANALYZED:进行索引,但是不进行分词,像身份证号,姓名,ID等,适用于精确索索

Field.Index.ANALYZED_NO_NORMS:进行分词但是不存储norms信息,这个norms中包括了创建索引的时间和权值等信息

Field.Index.NOT_ANALYZED_NO_NORMS:即不进行分词也不存储norms信息

Field.Index.NO:不进行索引  

最佳实践

Field.Index.NOT_ANALYZED_NO_NORMS, Field.Store.YES标识符(主键,文件名),电话号码,身份证号,姓名,日期

Field.Index.ANALYZED, Field.Store.YES文档标题和摘要

Field.Index.ANALYZED, Field.Store.NO文档正文

Field.Index.NO,Field.Store.YES文档类型,数据库主键(不进行索引)

Field.Index.NOT_ANALYZED,Field.Store.NO 隐藏关键字


搜索操作的步骤:

1.创建Directory

2.创建IndexReader

3.根据IndexReader创建IndexSearcher

4.创建搜索的Query

5.根据Searcher搜索并且返回TopDocs

6.根据TopDocs获取ScoreDoc对象

7.根据Seacher和ScoreDoc对象获取具体的Document对象

8.根据Document对象获取需要的值

9.关闭IndexReader

@Test
public void searchIndex() throws Exception {
	IndexReader reader = null;
	IndexSearcher search = null;
	reader = IndexReader.open(directory);
	search = new IndexSearcher(reader);
	
	QueryParser parser = new QueryParser(Version.LUCENE_35, "context", new StandardAnalyzer(Version.LUCENE_35));
	Query query = parser.parse("com.lelife.solrclient.job.SyschronizedPromotion");
	
	TopDocs tds = search.search(query, 10);
	ScoreDoc[] sds = tds.scoreDocs;
	if(null!=sds&&sds.length>0){
		for(ScoreDoc sd : sds){
			Document d = search.doc(sd.doc);
			log.debug(d.get("fileName") + "[" + d.get("filePath") + "]");
		}
	}else{
		log.debug("没有匹配的文档");
	}
	search.close();
	reader.close();
	log.debug("运行结束");
}

这里查询内容中包含com.lelife.solrclient.job.SyschronizedPromotion的文件,并打印文件名称和位置。


删除文档操作

删除有多种方式,精确和查询式删除,或者全删。

@Test
public void deleteIndex() throws Exception {
	IndexWriterConfig iwc = new IndexWriterConfig(Version.LUCENE_35, new StandardAnalyzer(Version.LUCENE_35));
	IndexWriter writer = null;
	writer = new IndexWriter(directory, iwc);
	writer.deleteAll();
//		writer.deleteDocuments(new Term("fileName","lelifeclient.log"));
//		QueryParser parser = new QueryParser(Version.LUCENE_35, "context", new StandardAnalyzer(Version.LUCENE_35));
//		Query query = parser.parse("com.lelife.solrclient.job.SyschronizedPromotion");
//		writer.deleteDocuments(query);
	writer.close();
	log.debug("运行结束");
}

indexWriter.deleteDocuments()文档并不会完全被删除,而是存储在一个回收站中,我们可以编写查询类来进行查询。

以下代码查看当前的索引情况:

@Test
public void showIndex() throws Exception {
	IndexReader indexReader = IndexReader.open(directory);
	log.debug("总存储量:" + indexReader.maxDoc());
	log.debug("存储的文档数:" + indexReader.numDocs());
	log.debug("被删除的文档:" + indexReader.numDeletedDocs());
}

恢复被删除的文档:

使用IndexReader可以有效的恢复删除到回收站的文档。

@Test
public void recoveryIndex() throws Exception {
	IndexReader indexReader = IndexReader.open(directory,false);
	indexReader.undeleteAll();
	indexReader.close();
}

清空回收站文档:

如果要清空回收站中的内容,需要使用IndexWriter中的forceMergeDeletes()方法。

@Test
public void forceDelete() throws Exception{
	IndexWriterConfig indexWriterConfig = new IndexWriterConfig(Version.LUCENE_35,new StandardAnalyzer(Version.LUCENE_35));
	IndexWriter indexWriter = new IndexWriter(directory, indexWriterConfig);
	indexWriter.forceMergeDeletes();
	indexWriter.close();
}

更新文档:

Luence并没有提供更新,这里的更新操作其实是先删除再添加的操作合集。

@Test
public void updateIndex() throws Exception{
	IndexWriterConfig indexWriterConfig = new IndexWriterConfig(Version.LUCENE_35,new StandardAnalyzer(Version.LUCENE_35));
	IndexWriter indexWriter = new IndexWriter(directory, indexWriterConfig);
	Document doc = null;
	File f = new File("D:/data/test");
	for(File file : f.listFiles()){
		doc = new Document();
		doc.add(new Field("context", new FileReader(file)));
		doc.add(new Field("fileName",file.getName(),Field.Store.YES,Field.Index.NOT_ANALYZED));
		doc.add(new Field("filePath",file.getPath(),Field.Store.YES,Field.Index.NOT_ANALYZED));
		indexWriter.updateDocument(new Term("fileName",file.getName()), doc);
	}
	indexWriter.close();
	log.debug("运行结束");
}

结束。

推荐您阅读更多有关于“ 入门 apache Solr Lucene 增删改查 ”的文章

上一篇:java读写Properties属性文件公用方法 下一篇:Log4J日志配置详解

猜你喜欢

发表评论:

评论:

回复 themebetter 评论于 2016-03-17 17:12
验证码老是失败
回复 java小强 评论于 2016-03-19 15:52
@themebetter:好的,我看下怎么回事。。。