lucene 实战(二)lucene 索引

lucene是一个提供搜索的工具,并不能实现内容的抓取。所有内容的获取完全依赖于自己的应用程序去实现或者第三方的工具来做。在apache lucene下面有一个子项目,Solr可以实现从关系型数据库中获取原始数据。只要拿到原始的文本数据,lucene就可以负责建立相关的索引。

创建索引

1.Field.Store.YES (NO)
存储域选项

设置为Y表示把这个域中的内容完全存储到文件中,方便进行文本的还原

设置为N表示把这个域的内容不存储到文件中,但是可以被索引,此时内容无法完全还原

2.Field.Index(索引选项)

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

Index.NOT_ANALYZED:进行素引,但是不进行分词,如果身份证号,姓名,lp等.适用干精确搜素

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

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

Index.NO:不进行索引。

/**
	 * 创建索引-cfl-2015年5月26日
	 */
	public void createIndex(){

		//用于写入索引文件的writer对象
		IndexWriter writer =null;

		try {

			//载入writer配置
			writer=new IndexWriter(directory,new IndexWriterConfig(Version.LUCENE_35,new StandardAnalyzer(Version.LUCENE_35)));
			Document doc=null;

			//遍历数组写入域信息
			for(int i=0;i<ids.length;i++){

				doc=new Document();
				doc.add(new Field("id",ids[i],Field.Store.YES,Field.Index.NOT_ANALYZED));
				doc.add(new Field("name",names[i],Field.Store.YES,Field.Index.NOT_ANALYZED));
				doc.add(new Field("mail",mails[i],Field.Store.YES,Field.Index.ANALYZED_NO_NORMS));
				doc.add(new Field("content",contents[i],Field.Store.NO,Field.Index.ANALYZED_NO_NORMS));
				writer.addDocument(doc);

				//取得含有特定字符的数组
				String strMail=mails[i].substring(mails[i].lastIndexOf("@")-1);
				System.out.println(strMail);

				//为指定域添加权重
				if(scoreMap.containsKey(strMail)){
					doc.setBoost(scoreMap.get(i));
				}else{
					doc.setBoost(0.5f);
				}

			}

			System.out.println("索引创建成功!");

		} catch (CorruptIndexException e) {
			e.printStackTrace();
		} catch (LockObtainFailedException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}finally{
			closeWriter(writer);
		}

	}

在配置IndexWriterConfig时,需要注意的是配置指定的版本号。这里还是体现了lucene开发者成熟的设计理念的。为用户在自行选择版本的给于了充分的自由度的。

创建索引过程类似于关系型数据库中的记录、字段的创建,创建doc相当于创建一条条的数据库记录。而field的创建对应着字段的创建。

查询

1.一般查询

/**
	 * 查询索引的值-cfl-2015年5月26日
	 */
	public void queryIndex(){
		//1.创建indexReader
		IndexReader reader=null;
		try {
			//可以有效通过reader获取文档的数量
			reader=IndexReader.open(directory);
			System.out.println("maxDocs:"+reader.maxDoc());
			System.out.println("numDocs:"+reader.numDocs());
			System.out.println("deleteDocs:"+reader.numDeletedDocs());
		} catch (CorruptIndexException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}finally{
			closeReader(reader);
		}

	}

利用IndexReader来获取索引文件目录中总文件数,索引文件数,已删除文件数信息。

2.根据关键词Term查询

/**
	 * 精确查询索引根据关键字-cfl-2015年5月27日
	 */
	public void queryIndexByTerm(){
		IndexReader reader=null;
		try {
			reader=IndexReader.open(directory);
			IndexSearcher searcher=new IndexSearcher(reader);
			TermQuery query=new TermQuery(new Term("content","bootst"));
			TopDocs topDocs=searcher.search(query, 10);
			for(ScoreDoc td:topDocs.scoreDocs){
				System.out.println(td.toString());
				System.out.println(searcher.doc(td.doc).get("name"));
			}
		} catch (CorruptIndexException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}finally{
			closeReader(reader);
		}

	}

查询存在于content域中含有关键词bootst的数据。

IndexSearcher searcher=new IndexSearcher(reader);
			TermQuery query=new TermQuery(new Term("content","bootst"));
			TopDocs topDocs=searcher.search(query, 10);

这样的一个过程类似在关系数据库查询过程中

1.利用reader建立searcher对象

2.配置Term关键词

3.查询10条数据

删除

1.指定删除

/**
	 * 删除指定索引-cfl-2015年5月26日
	 */
	public void deleteIndex(){
		IndexWriter writer=null;
		try {
			writer=new IndexWriter(directory,new IndexWriterConfig(Version.LUCENE_35,new StandardAnalyzer(Version.LUCENE_35)));
			//term精确查找的值
			writer.deleteDocuments(new Term("id","01"));
			System.out.println("已删除指定索引!" );
		} catch (CorruptIndexException e) {
			e.printStackTrace();
		} catch (LockObtainFailedException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}finally{
			closeWriter(writer);
		}
	}

利用还是Term关键词来删除指定域数据。

2.删除所有

/**
	 * 删除所有索引-cfl-2015年5月26日
	 */
	public void deleteAllIndex(){
		IndexWriter writer=null;
		try {
			writer=new IndexWriter(directory,new IndexWriterConfig(Version.LUCENE_35,new StandardAnalyzer(Version.LUCENE_35)));
			writer.deleteAll();
		} catch (CorruptIndexException e) {
			e.printStackTrace();
		} catch (LockObtainFailedException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}finally{
			closeWriter(writer);
		}
	}

这里删除所有的,则直接利用Writer对象即可。需要注意的是这里其实类似在windows中的操作,将资源放在了回收站中并没有彻底删除。

3.强制删除(从回收站中清空)

	/**
	 * 强制删除-cfl-2015年5月27日
	 */
	public void forceDelete() {
		IndexWriter writer = null;
		try {
			writer = new IndexWriter(directory, new IndexWriterConfig(
					Version.LUCENE_35, new StandardAnalyzer(Version.LUCENE_35)));
			writer.forceMergeDeletes();
		} catch (CorruptIndexException e) {
			e.printStackTrace();
		} catch (LockObtainFailedException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			closeWriter(writer);
		}
	}

这里强制删除会牺牲一些机器的性能,不推荐使用。lucene在索引增多之后,会根据情况来自动整理。这里删除之后不会再恢复。

恢复

从回收站中恢复索引文件

/**
	 * 恢复索引-cfl-2015年5月26日
	 */
	public void unDeleteIndex(){
		IndexReader reader=null;

		try {
			//取得指定目录文件夹下,设置只读为false
			reader=IndexReader.open(directory,false);
			reader.undeleteAll();
			System.out.println("已恢复所有删除的索引!");
		} catch (CorruptIndexException e) {
			e.printStackTrace();
		} catch (LockObtainFailedException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}finally{
			closeReader(reader);
		}

	}

直接利用reader自带的方法undeleteAll()即可。

设置权重

提高被搜索出的频率,类似百度做的seo。

//为指定域添加权重
				if(scoreMap.containsKey(strMail)){
					doc.setBoost(scoreMap.get(i));
				}else{
					doc.setBoost(0.5f);
				}
时间: 2024-11-08 10:51:26

lucene 实战(二)lucene 索引的相关文章

Lucene基础(二)--索引的操作

索引的操作 我们建立所有就是要达到快速检索的目的,对数据能够方面便的查找,和数据库类似,索引也有自己的相关增删改查的操作. 在索引的增删改查中,增删改属于写操作,主要是有IndexWrite提供的方法处理:而查显而易见,读操作,使用IndexSeacher 提供的方法来实现.在Lucene的官方文档找到 org.apache.lucene.index.IndexWriter 这个类,我们就可以看到他很多方法. 创建索引 如同上一章里面的代码,创建索引时先建立文件,创建索引的域,再使用IndexW

Lucene实战(第2版)》

<Lucene实战(第2版)>基于Apache的Lucene 3.0,从Lucene核心.Lucene应用.案例分析3个方面详细系统地介绍了Lucene,包括认识Lucene.建立索引.为应用程序添加搜索功能.高级搜索技术.扩展搜索.使用Tika提取文本.Lucene的高级扩展.使用其他编程语言访问Lucene.Lucene管理和性能调优等内容,最后还提供了三大经典成功案例,为读者展示了一个奇妙的搜索世界. 首先你先确定Lucene的版本,然后查一下对应官方的api文档,看看你用的那个方法是实

【Lucene】Apache Lucene全文检索引擎架构之入门实战

Lucene是一套用于全文检索和搜寻的开源程式库,由Apache软件基金会支持和提供.Lucene提供了一个简单却强大的应用程式接口,能够做全文索引和搜寻.在Java开发环境里Lucene是一个成熟的免费开源工具.就其本身而言,Lucene是当前以及最近几年最受欢迎的免费Java信息检索程序库.--<百度百科> 这篇博文主要从两个方面出发,首先介绍一下Lucene中的全文搜索原理,其次通过程序示例来展现如何使用Lucene.关于全文搜索原理部分我上网搜索了一下,也看了好几篇文章,最后在写这篇文

【Lucene】Apache Lucene全文检索引擎架构之入门实战1

Lucene是一套用于全文检索和搜寻的开源程式库,由Apache软件基金会支持和提供.Lucene提供了一个简单却强大的应用程式接口,能够做全文索引和搜寻.在Java开发环境里Lucene是一个成熟的免费开源工具.就其本身而言,Lucene是当前以及最近几年最受欢迎的免费Java信息检索程序库.——<百度百科> 这篇博文主要从两个方面出发,首先介绍一下Lucene中的全文搜索原理,其次通过程序示例来展现如何使用Lucene.关于全文搜索原理部分我上网搜索了一下,也看了好几篇文章,最后在写这篇文

elasticsearch系列二:索引详解(快速入门、索引管理、映射详解、索引别名)

一.快速入门 1. 查看集群的健康状况 http://localhost:9200/_cat http://localhost:9200/_cat/health?v 说明:v是用来要求在结果中返回表头 状态值说明 Green - everything is good (cluster is fully functional),即最佳状态Yellow - all data is available but some replicas are not yet allocated (cluster i

【Lucene】Apache Lucene全文检索引擎架构之搜索功能

上一节主要总结了一下Lucene是如何构建索引的,这一节简单总结一下Lucene中的搜索功能.主要分为几个部分,对特定项的搜索:查询表达式QueryParser的使用:指定数字范围内搜索:指定字符串开头搜索以及多条件查询. 1. 对特定项的搜索 要使用Lucene的搜索功能,首先得有索引,也就是说Lucene首先得针对特定的文件生成特定的索引,然后我们才能搜索,这在第一节里描述的很清楚,那么构建索引的例子也是使用第一节中的例子,在这就不再赘述了,然后生成了索引后,如何来搜索呢?先看第一种搜索方式

Python爬虫实战二之爬取百度贴吧帖子

大家好,上次我们实验了爬取了糗事百科的段子,那么这次我们来尝试一下爬取百度贴吧的帖子.与上一篇不同的是,这次我们需要用到文件的相关操作. 前言 亲爱的们,教程比较旧了,百度贴吧页面可能改版,可能代码不好使,八成是正则表达式那儿匹配不到了,请更改一下正则,当然最主要的还是帮助大家理解思路. 2016/12/2 本篇目标 1.对百度贴吧的任意帖子进行抓取 2.指定是否只抓取楼主发帖内容 3.将抓取到的内容分析并保存到文件 1.URL格式的确定 首先,我们先观察一下百度贴吧的任意一个帖子. 比如:ht

二叉索引树BIT

定义     二叉索引树,binary index tree,又名树状数组,或Fenwick Tree,因为本算法由Fenwick创造.     对于数组A,定义Query(i,j) = Ai +Ai+1 + - + Aj.     比较好的做法:使用前缀和,Sum(j) – Sum(i-1)即可得到Query(i,j)     BIT即为解决此类区间查询而大展身手,因为预处理时间为O(n),之后的查询时间为O(1),是属于典型的在线算法(关于在线算法,通俗地可以理解为,做一次预处理,提供多次"

云计算设计模式(十二)——索引表模式

创建索引过的被查询条件经常被引用的数据存储等领域.这种模式可以通过允许应用程序更快速地定位数据来从数据存储中检索提高查询性能. 背景和问题 许多数据存储通过使用主键组织为实体的集合的数据.应用程序可以使用此键来查找和检索数据.图1显示了一个数据存储区保持顾客的信息的例子.主键是客户ID. 图1  - 按主键组织的客户信息(客户ID) 而主键是该取基于该关键字的值的数据的查询宝贵的,应用程序可能不能够使用主键是否需要基于其它字段来检索数据.在顾客例如,应用程序不能使用该客户ID主键来检索客户,如果

C++实用数据结构:二叉索引树

看下面这个问题(动态连续和查询): 有一个数组A(长度为n),要求进行两种操作: add(i,x):让Ai增大x: query(a,b):询问Aa+Aa+1+...+Ab的和: 若进行模拟,则每次query操作的最坏的时间复杂度为O(n),在n较大时速度较慢.用前缀和也不能提高效率(每次add操作最坏为O(n)).有一种数据结构,可以在O(n)时间里初始化,用O(logn)的速度执行add操作或查询前缀和,从而执行query操作. 首先,我们来介绍“lowbit”.对于一个数x,lowbit(x