码迷,mamicode.com
首页 > Web开发 > 详细

lucene 实战(二)lucene 索引

时间:2015-05-27 17:27:19      阅读:178      评论:0      收藏:0      [点我收藏+]

标签:


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




lucene 实战(二)lucene 索引

标签:

原文地址:http://blog.csdn.net/cfl20121314/article/details/46047621

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!