Lucene

以前使用数据库精确搜索,但是其使用(%和like)导致其速度慢、功能不强、性能低;所以我们今天来学习Lucene相关的搜索引擎。

Lucene是当前非常流行的、免费的Java信息搜索(IR)库。Lucene是Apache下一个著名的开源搜索引擎内核,它基于Java技术,可以处理索引、拼写检查、点击高亮和其他分词等技术。Lucene并不关心数据源、数据格式、甚至数据的语言,Lucene更不会关心搜索的界面会是怎样,因为这些工作都是由基于Lucene的程序来完成,因此Lucene使用于几乎所有以文本内容为主的数据检索功能。

Solr

Lucene主要实现索引和查询的核心功能及API,但并不是一个完整的产品,而Solr是一个独立的企业级搜索应用服务器,它对外提供类似于Web-service的API接口,用户可以通过Http请求,向搜索引擎服务器提交一定格式的XML文件,生成索引。并且提供灵活的Schema配置、多核心支持、面搜索(Faceted Search)等。同时实现了可配置、可扩展并对查询性能进行了优化,并且提供了一个完善的功能管理界面,是一款非常优秀的全文搜索引擎。Solr 主要特性有:强大的全文检索功能,高亮显示检索结果,动态集群,数据库接口和电子文档(Word ,PDF 等)的处理。而且Solr 具有高度的可扩展,支持分布搜索和索引的复制。

Nutch

Nutch和Solr原来都是Lucene下的子项目。但后来Nutch独立成为独立项目。Nutch是2004年由俄勒冈州立大学开源实验室模仿Google搜索引擎创立的开源搜索引擎,后归于Apache旗下。Nutch 是一个开源Java实现的搜索引擎。它提供了我们运行自己的搜索引擎所需的全部工具。包括全文搜索和Web爬虫

Hadoop

Hadoop 是一个开源的可运行于大规模集群上的分布式并行编程框架,由于分布式存储对于分布式编程来说是必不可少的,这个框架中还包含了一个分布式文件系统HDFS( Hadoop Distributed File System )。Hadoop原来是Nutch下的分布式任务子项目,现在也成为Apache下的顶级项目。Nutch可以利用Hadoop进行分布式多任务抓取和分析存储工作。Doug Cutting 把 Nutch 中的分布式文件系统以及实现 MapReduce 算法的代码独立出来形成了一个新的开源项 Hadoop。Nutch 也演化为基于 Lucene 全文检索以及 Hadoop 分布式计算平台的一个开源搜索引擎Hadoop 实现了 Google 的 MapReduce 编程模型,提供了简单易用的编程接口,也提供了它自己的分布式文件系统 HDFS,与 Google 不同的是,Hadoop 是开源的,任何人都可以使用这个框架来进行并行编程。如果说分布式并行编程的难度足以让普通程序员望而生畏的话,开源的 Hadoop 的出现极大的降低了它的门槛。

略微了解Lucene相关技术,现在让我们新建一个maven项目,运用一下!!!

pom.xml

<!--核心包-->
  	<dependency>
     	<groupId>org.apache.lucene</groupId>
     	<artifactId>lucene-core</artifactId>
     	<version>5.3.1</version>
    </dependency>
    <!--一般分词器,适用于英文分词-->
    <dependency>
    	<groupId>org.apache.lucene</groupId>
    	<artifactId>lucene-analyzers-common</artifactId>
    	<version>5.3.1</version>
    </dependency>
  	<!--中文分词器-->
    <dependency>
   		<groupId>org.apache.lucene</groupId>
   		<artifactId>lucene-analyzers-smartcn</artifactId>
   		<version>5.3.1</version>
   	</dependency>
    <!--对分词索引查询解析-->
  	<dependency>
  		<groupId>org.apache.lucene</groupId>
  		<artifactId>lucene-queryparser</artifactId>
  		<version>5.3.1</version>
 	</dependency>
 	<!--检索关键字高亮显示-->
 	<dependency>
 	    <groupId>org.apache.lucene</groupId>
 	    <artifactId>lucene-highlighter</artifactId>
 	    <version>5.3.1</version>
 	</dependency>

Indexer.java

package com.test;

import java.nio.file.Paths;

import org.apache.lucene.analysis.cn.smart.SmartChineseAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.IntField;
import org.apache.lucene.document.StringField;
import org.apache.lucene.document.TextField;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;

public class Indexer {
	//从数据库来看,这就是一个表的三个字段ids,citys,descs
	private Integer ids[]={1,2,3};
	private String citys[]={"《从你的全世界路过》","《子不语》","《平凡的世界》"};
	private String descs[]={
			"不想从你的全世界路过。",
			"子不语。",
			"平凡的世界。"
	};
	//创建一个文件夹,也就是索引
	private Directory dir;
	//写索引
	private IndexWriter getWriter()throws Exception{
		//中文分词器
		SmartChineseAnalyzer analyzer=new SmartChineseAnalyzer();
		IndexWriterConfig iwc=new IndexWriterConfig(analyzer);
		IndexWriter writer=new IndexWriter(dir, iwc);
		return writer;
	}
	
	private void index(String indexDir)throws Exception{
		dir=FSDirectory.open(Paths.get(indexDir));
		//写索引
		IndexWriter writer=getWriter();
		for(int i=0;i<ids.length;i++){
			Document doc=new Document();
			doc.add(new IntField("id", ids[i], Field.Store.YES));
			doc.add(new StringField("city",citys[i],Field.Store.YES));
			doc.add(new TextField("desc", descs[i], Field.Store.YES));
			writer.addDocument(doc);
			}
		writer.close();
	}
	

	public static void main(String[] args) throws Exception {
		new Indexer().index("D:\\Lucene");

		System.out.println("Success Indexer");

	}

}

ReaderByIndexerTest.java

package com.test;

import java.io.StringReader;
import java.nio.file.Paths;

import org.apache.lucene.analysis.TokenStream;
import org.apache.lucene.analysis.cn.smart.SmartChineseAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.ScoreDoc;
import org.apache.lucene.search.TopDocs;
import org.apache.lucene.search.highlight.Fragmenter;
import org.apache.lucene.search.highlight.Highlighter;
import org.apache.lucene.search.highlight.QueryScorer;
import org.apache.lucene.search.highlight.SimpleHTMLFormatter;
import org.apache.lucene.search.highlight.SimpleSpanFragmenter;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;

public class ReaderByIndexerTest {
	public static void search(String indexDir, String par) throws Exception{
		//得到读取索引文件的路径
		Directory dir = FSDirectory.open(Paths.get(indexDir));
		//通过dir得到的路径下的所有的文件
		IndexReader reader = DirectoryReader.open(dir);
		//建立索引查询器
		IndexSearcher searcher = new IndexSearcher(reader);
		//中文分词器
		SmartChineseAnalyzer analyzer=new SmartChineseAnalyzer();
		//建立查询解析器
		/**			 
		 * 第一个参数是要查询的字段;			 
		 * 第二个参数是分析器Analyzer			 
		 * */			
		QueryParser parser = new QueryParser("desc", analyzer);
		//根据传进来的par查找
		Query query = parser.parse(par);
		//计算索引开始时间
		long start = System.currentTimeMillis();
		//开始查询
		/**			 
		 * 第一个参数是通过传过来的参数来查找得到的query;			 
		 * 第二个参数是要出查询的行数			 
		 * */
		TopDocs topDocs = searcher.search(query, 10);
		//索引结束时间
		long end = System.currentTimeMillis();
		System.out.println("匹配"+par+",总共花费了"+(end-start)+"毫秒,共查到"+topDocs.totalHits+"条记录。");
		//高亮显示start
		//算分
		QueryScorer scorer=new QueryScorer(query);
		//显示得分高的片段
		Fragmenter fragmenter=new SimpleSpanFragmenter(scorer);
		//设置标签内部关键字的颜色
		//第一个参数:标签的前半部分;第二个参数:标签的后半部分。
		SimpleHTMLFormatter simpleHTMLFormatter=new SimpleHTMLFormatter("<b><font color='red'>","</font></b>");
		//第一个参数是对查到的结果进行实例化;第二个是片段得分(显示得分高的片段,即摘要)
		Highlighter highlighter=new Highlighter(simpleHTMLFormatter, scorer);
		//设置片段
		highlighter.setTextFragmenter(fragmenter);
		//高亮显示end
		//遍历topDocs
		/**				 
		 * ScoreDoc:是代表一个结果的相关度得分与文档编号等信息的对象。
		  	* scoreDocs:代表文件的数组
		  	* 				 
		  	* @throws Exceptio
		  	* */				
		for(ScoreDoc scoreDoc : topDocs.scoreDocs){	
			//获取文档
			Document document = searcher.doc(scoreDoc.doc);
			//输出全路径
			System.out.println(document.get("city"));
			System.out.println(document.get("desc"));
			String desc = document.get("desc");
			if(desc!=null){	
				//把全部得分高的摘要给显示出来
				//第一个参数是对哪个参数进行设置;第二个是以流的方式读入
				TokenStream tokenStream=analyzer.tokenStream("desc", new StringReader(desc));
				//获取最高的片段
				System.out.println(highlighter.getBestFragment(tokenStream, desc));
				}
			}
		reader.close();	}
	//开始测试
	public static void main(String[] args) {
		//索引指定的路径
		String indexDir = "D:\\Lucene";
		//查询的字段
		String par = "平凡之路";
		try {
			search(indexDir,par);
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
	}		
			
		
		
}

 

  • 0
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ZBY52031

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值