Lucene学习总结

一)       什么是Lucene?

  

Lucene是apache软件基金会发布的一个开放源代码的全文检索引擎工具包,由资深全文检索专家Doug Cutting所撰写,它是一个全文检索引擎的架构,提供了完整的创建索引和查询索引,以及部分文本分析的引擎,Lucene的目的是为软件开发人员提供一个简单易用的工具包,以方便在目标系统中实现全文检索的功能,或者是以此为基础建立起完整的全文检索引擎,Lucene在全文检索领域是一个经典的祖先,现在很多检索引擎都是在其基础上创建的,思想是相通的。

即:Lucene是根据关健字来搜索的文本搜索工具,只能在某个网站内部搜索文本内容,不能跨网站搜索

二)       Lucene通常用在什么地方?

 

Lucece不能用在互联网搜索(即像百度那样),只能用在网站内部的文本搜索(即只能在CRM,RAX,ERP内部使用),但思想是相通的。如图:

Lucene用在服务端三层结构中的哪一层?


三)       Lucene中存的什么内容?

Lucene中存的就是一系列的二进制压缩文件和一些控制文件,它们位于计算机的硬盘上,

这些内容统称为索引库,索引库有二部份组成:

(1)原始记录

     存入到索引库中的原始文本,例如:中国是一个伟大的国家

(2)词汇表

     按照一定的拆分策略(即分词器)将原始记录中的每个字符拆开后,存入一个供将来搜索的表


Lucene索引库结构与原理图:




四)       为什么网站内部有些地方要用Lucene来索搜,而不全用SQL来搜索?


(1)SQL只能针对数据库表搜索,不能直接针对硬盘上的文本搜索

(2)SQL没有相关度排名

(3)SQL搜索结果没有关健字高亮显示

(4)SQL需要数据库的支持,数据库本身需要内存开销较大,例如:Oracle

(5)SQL搜索有时较慢,尤其是数据库不在本地时,超慢,例如:Oracle

五) 使用Lucene的流程图

 1.Lucene程序宏观结构

   

2.Lucene索引库创建的过程

 

3.Lucene索引库查询的过程

两个重要的类:



图解TopDocs和ScoreDoc这二个类


创建索引库:

1) 创建JavaBean对象

2) 创建Docment对象

3) 将JavaBean对象所有的属性值,均放到Document对象中去,属性名可以和JavaBean相同或不同

4) 创建IndexWriter对象

5) 将Document对象通过IndexWriter对象写入索引库中

6) 关闭IndexWriter对象

根据关键字查询索引库中的内容:

1) 创建IndexSearcher对象

2) 创建QueryParser对象

3) 创建Query对象来封装关键字

4) 用IndexSearcher对象去索引库中查询符合条件的前100条记录,不足100条记录的以实际为准

5) 获取符合条件的编号

6) 用indexSearcher对象去索引库中查询编号对应的Document对象

7) 将Document对象中的所有属性取出,再封装回JavaBean对象中去,并加入到集合中保存,以备将之用

五)Lucene实例

准备工作:

导入Lucene相关的jar包

  lucene-core-3.0.2.jar【Lucene核心】

  lucene-analyzers-3.0.2.jar【分词器】

  lucene-highlighter-3.0.2.jar【Lucene会将搜索出来的字,高亮显示,提示用户】

  lucene-memory-3.0.2.jar【索引库优化策略】

创建实体类:

  

public class Article {
	private Integer id;//标题
	private String title;//标题
	private String content;//内容
	public Article(){}
	public Article(Integer id, String title, String content) {
		this.id = id;
		this.title = title;
		this.content = content;
	}
	public Integer getId() {
		return id;
	}
	public void setId(Integer id) {
		this.id = id;
	}
	public String getTitle() {
		return title;
	}
	public void setTitle(String title) {
		this.title = title;
	}
	public String getContent() {
		return content;
	}
	public void setContent(String content) {
		this.content = content;
	}
	@Override
	public String toString() {
		return "编号:"+id+"\n标题:"+title+"\n内容:"+content;
	}
	
}

	/**
	 * 创建索引库
	 * 将Article对象放入索引库的原始记录表中,从而形成词汇表
	 * @throws Exception 
	 */
	@Test
	public void createIndexDB() throws Exception{
		///创建Article对象
		Article article=new Article(1,"中","中国是一个伟大的国家");
		//创建Document对象
		Document document=new Document();
		/**
		 * 
		 * 参数一:document对象中的属性名叫id,article对象中的属性名叫id,项目中提倡相同
		 * 参数二:document对象中的属性id,与article对象中相同
		 * 参数三:是否将id属性值存入由原始记录表中转存入词汇表
		 *         Store.YES表示该属性值会存入原始记录表
		 *         Store.No表示该属性值不会存入原始记录表
		 *         项目中提倡非id值都存入词汇表
		 * 参数四:是否将id属性值进行分词算法
		 *         Index.ANALYZED:表示该属性值会进行词汇拆分
		 *        Index.NOT.ANALYZED表示该属性值不会进行词汇拆分
		 *         项目中提倡非id值都进行词汇拆分
		 * 
		 */
		document.add(new Field("id",article.getId().toString(),Store.YES,Index.ANALYZED));
		document.add(new Field("title",article.getTitle(),Store.YES, Index.ANALYZED));
		document.add(new Field("content", article.getContent(), Store.YES, Index.ANALYZED));
	
		//创建IndexWriter字符流
		/**
		 * 参数一:lucene索引库最终应对于硬盘中的目录,例如:E:/indexDB
		 * 参数二:采用什么策略将文本拆分,一个策略就是一个具体的实现类
		 * 参数三:最多将文本拆分出多少词汇,LIMITED表示一万个,即只取前一万个词汇,
		 * 如果不足一万,以实际为主
		 */
		Directory directory=FSDirectory.open(new File("E:/IndexDB"));
		Version version=Version.LUCENE_30;
		Analyzer analyzer=new StandardAnalyzer(version);
		MaxFieldLength maxFieldLength=MaxFieldLength.LIMITED;
		IndexWriter indexWriter=new IndexWriter(directory, analyzer, maxFieldLength);
		//将document对象写入lucene索引库
		indexWriter.addDocument(document);
		indexWriter.close();
	}
	/**
	 * 根据关键字从索引库中搜索符合条件的内容
	 * @throws Exception 
	 */
	
	@Test
	public void findIndexDB() throws Exception{
		//准备工作
		String keywords="中";
		List<Article> articles=new ArrayList<Article>();
		Directory directory = FSDirectory.open(new File("E:/IndexDB"));
		Version version = Version.LUCENE_30;
        Analyzer analyzer=new StandardAnalyzer(version);
        MaxFieldLength maxFieldLength = MaxFieldLength.LIMITED;
        
        //创建IndexSearcher字符流对象
        IndexSearcher indexSearcher=new IndexSearcher(directory);
        
        //创建查询解析器对象
        /**
         * 参数一:使用分词器的版本,提倡使用该jar包中的最高版本
         * 参数二:针对document对象中的那个属性进行搜索
         */
        QueryParser queryParser=new QueryParser(version,"content",analyzer);
        Query query = queryParser.parse(keywords);
        //根据关键字,去索引库中的词汇表搜索
        /**
         * 参数一:表示封装关键字查询对象,其他QueryParen表示查询解析器
         * 参数二:Max_RECODER:表示如果根据关键字搜索出来的内容较多,只取前MAX_RECORD个内容
         * 不足max_reord个数的话,以实际为准
         */
        int MAX_RECORD=100;
        TopDocs topDocs = indexSearcher.search(query, MAX_RECORD);
        //迭代词汇表中符合条件的编号
        for(int i=0;i<topDocs.scoreDocs.length;i++){
        	//取出封装编号和分数的ScoreDoc对象
        	ScoreDoc scoreDoc = topDocs.scoreDocs[i];
        	//取出每一个编号,例如:0,1,2
        	int no = scoreDoc.doc;
        	//根据编号去索引库中的原始记录表中查询对应的docuemnt对象
        	Document document = indexSearcher.doc(no);
        	//获取docuemnt对象中的三个属性值
        	String id= document.get("id");
        	String title = document.get("title");
            String content = document.get("content");
        	Article article=new Article(Integer.valueOf(id), title, content);
        	articles.add(article);
         }
          for(Article a:articles){
        	  System.out.println(a.toString());
          }
	}
	


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值