搜索引擎之全文搜索算法功能实现(基于Lucene)
之前做去转盘网的时候,我已经公开了非全文搜索的代码,需要的朋友希望能够前去阅读我的博客。本文主要讨论如何进行全文搜索,由于本人花了很长时间设计了新作:观点,观点对全文搜索的要求还是很高的,所以我又花了不少时间研究全文搜索,你可以先体验下:点我搜索。废话也不多说了,直接上代码:
public Map<String,Object> articleSearchAlgorithms(SearchCondition condition,IndexSearcher searcher) throws ParseException, IOException{
Map<String,Object> map =new HashMap<String,Object>();
String[] filedsList=condition.getFiledsList();
String keyWord=condition.getKeyWord();
int currentPage=condition.getCurrentPage();
int pageSize=condition.getPageSize();
String sortField=condition.getSortField();
boolean isASC=condition.isDESC();
String sDate=condition.getsDate();
String eDate=condition.geteDate();
String classify=condition.getClassify();
//过滤终结字符
keyWord=escapeExprSpecialWord(keyWord);
BooleanQuery q1 = new BooleanQuery();
BooleanQuery q2 = new BooleanQuery();
BooleanQuery booleanQuery = new BooleanQuery(); //boolean查询
if(classify!=null&&(classify.equals("guanzhi")||classify.equals("opinion")||classify.equals("write"))){
String typeId="1";//默认言论
if(classify.equals("guanzhi")){
typeId="2";
}
if(classify.equals("opinion")){
typeId="3";
}
Query termQuery = new TermQuery(new Term("typeId",typeId));
q1.add(termQuery,BooleanClause.Occur.MUST);
}
if(sDate!=null&&eDate!=null){//是否范围查询由这两个参数决定
Query rangeQuery = new TermRangeQuery("writingTime", new BytesRef(sDate), new BytesRef(eDate),true, true);
q1.add(rangeQuery,BooleanClause.Occur.MUST);
}
Sort sort = new Sort(); // 排序
sort.setSort(SortField.FIELD_SCORE);
if(sortField!=null){
sort.setSort(new SortField(sortField, SortField.Type.STRING, isASC));
}
int start = (currentPage - 1) * pageSize;
int hm = start + pageSize;
TopFieldCollector res = TopFieldCollector.create(sort,hm,false, false, false, false);
//完全匹配查询
Term t0=new Term(filedsList[1],keyWord);
TermQuery termQuery = new TermQuery(t0);//两种高度匹配的查询
q2.add(termQuery,BooleanClause.Occur.SHOULD);
//前缀匹配
Term t1=new Term(filedsList[1],keyWord);
PrefixQuery prefixQuery=new PrefixQuery(t1);
q2.add(prefixQuery,BooleanClause.Occur.SHOULD);
//短语,相似度匹配,适用于分词的内容
for(int i=0;i<filedsList.length;i++){ //多字段term查询算法
if(i!=1){
PhraseQuery phraseQuery=new PhraseQuery();
Term ts0=new Term(filedsList[i],keyWord);
phraseQuery.add(ts0);
FuzzyQuery fQuery=new FuzzyQuery(new Term(filedsList[i],keyWord),2);//最后相似度查询
q2.add(phraseQuery,BooleanClause.Occur.SHOULD);
q2.add(fQuery,BooleanClause.Occur.SHOULD);//后缀相似的拿出来
}
}
MultiFieldQueryParser queryParser = new MultiFieldQueryParser(Version.LUCENE_47,filedsList,analyzer);
queryParser.setDefaultOperator(QueryParser.AND_OPERATOR);
Query query = queryParser.parse(keyWord);
q2.add(query,BooleanClause.Occur.SHOULD);
//必须加逻辑判断,否则结果是不同的
if(q1!=null && q1.toString().length()>0){
booleanQuery.add(q1,BooleanClause.Occur.MUST);
}
if(q2!=null && q2.toString().length()>0){
booleanQuery.add(q2,BooleanClause.Occur.MUST);
}
searcher.search(booleanQuery, res);
long amount = res.getTotalHits();
TopDocs tds = res.topDocs(start, pageSize);
map.put("amount",amount);
map.put("tds",tds);
map.put("query",booleanQuery);
return map;
}
注意下:上面代码的搜索条件(SearchCondition )是观点网的具体需求,您可以按照您自己的搜索条件做改动,这里也很难适配所有读者。
public Map<String, Object> searchArticle(SearchCondition condition) throws Exception{
Map<String,Object> map =new HashMap<String,Object>();
List<Write> list=new ArrayList<Write>();
DirectoryReader reader=condition.getReader();
String URL=condition.getURL();
boolean isHighligth=condition.isHighlight();
String keyWord=condition.getKeyWord();
IndexSearcher searcher=getSearcher(reader,URL);
try{
Map<String,Object> output=articleSearchAlgorithms(condition,searcher);
if(output==null){
map.put("amount",0L);
map.put("source",null);
return map;
}
map.put("amount", output.get("amount"));
TopDocs tds = (TopDocs) output.get("tds");
ScoreDoc[] sd = tds.scoreDocs;
Query query =(Query) output.get("query");
for (int i = 0; i < sd.length; i++) {
Document doc = searcher.doc(sd[i].doc);
String id = doc.get("id");
/**********************start*************************需要处理的放一块儿********************/
String temp=doc.get("title");
String title =temp; //默认不高亮
if(isHighligth){
//高亮文章标题
Highlighter highlighterTitle = new Highlighter(simpleHTMLFormatter, new QueryScorer(query));
highlighterTitle.setTextFragmenter(new SimpleFragmenter(40)); // 字长度
TokenStream ts = analyzer.tokenStream("title", new StringReader(temp));
title= highlighterTitle.getBestFragment(ts,temp);
if(title==null){
title=temp.replace(keyWord,"<span style='color:red'>"+keyWord+"</span>");//高亮处理插件bug,加这句话避免
}
}
String temp1=HtmlEnDecode.htmlEncode(doc.get("content"));
String content=temp1;//使用自己封装的方法来转义
if(isHighligth){
//做高亮处理,content
Highlighter highlighterContent = new Highlighter(simpleHTMLFormatter, new QueryScorer(query));
highlighterContent.setTextFragmenter(new SimpleFragmenter(Constant.HIGHLIGHT_CONTENT_LENGTH)); // 字长度
//temp1=StringEscapeUtils.escapeHtml(temp1);//将汉字转义导致高亮失效
TokenStream ts1 = analyzer.tokenStream("content", new StringReader(temp1));
content = highlighterContent.getBestFragment(ts1,temp1);
if(content==null){
content=temp1.replace(keyWord,"<span style='color:red'>"+keyWord+"</span>");//高亮处理插件bug,加这句话避免
//假设遇上这种情况做处理,其他的高亮器会自动截图
content=subContent(content);//截取处理
content=HtmlEnDecode.htmldecode(content);//html解码
content=SubStringHTML.sub(content,Constant.HIGHLIGHT_CONTENT_LENGTH);
}
}
/*---------------------------------------不断变动的数据放一块儿----------------------------*/
Write write=writeDao.getArticle(Long.parseLong(id));
if(write!=null){
write.setTitle(title);
write.setContent(content);
Date writingTime=write.getWritingTime();
String timeGap=DateUtil.dateGap(writingTime);//timeGap
write.setTimeGap(timeGap);
list.add(write);
}
}
}catch(Exception e){
e.printStackTrace();
}
map.put("source",list);
return map;
}
注意上面,这是具体的搜索代码,不同的应用场景有不同的需求,请您按照自己的需求封装对象,查询数据库等,代码毫无保留,绝对可用。
如果有什么疑问可以加qq群:284205104 如果群满了就麻烦去趟去转盘找下最新的群加了即可,谢谢您的阅读。
搜索引擎之全文搜索算法功能实现(基于Lucene)的更多相关文章
- 8 个基于 Lucene 的开源搜索引擎推荐
Lucene是一种功能强大且被广泛使用的搜索引擎,以下列出了8种基于Lucene的搜索引擎,你可以想象它们有多么强大. 1. Apache Solr Solr 是一个高性能,采用Java5开发,基于L ...
- Apache Solr采用Java开发、基于Lucene的全文搜索服务器
http://docs.spring.io/spring-data/solr/ 首先介绍一下solr: Apache Solr (读音: SOLer) 是一个开源.高性能.采用Java开发.基于Luc ...
- 通通WPF随笔(1)——基于lucene.NET让ComboBox拥有强大的下拉联想功能
原文:通通WPF随笔(1)--基于lucene.NET让ComboBox拥有强大的下拉联想功能 我一直很疑惑百度.谷哥搜索框的下拉联想功能是怎么实现的?是不断地查询数据库吗?其实到现在我也不知道,他们 ...
- Lucene5.5.4入门以及基于Lucene实现博客搜索功能
前言 一直以来个人博客的搜索功能很蹩脚,只是自己简单用数据库的like %keyword%来实现的,所以导致经常搜不到想要找的内容,而且高亮显示.摘要截取等也不好实现,所以决定采用Lucene改写博客 ...
- 聊聊基于Lucene的搜索引擎核心技术实践
最近公司用到了ES搜索引擎,由于ES是基于Lucene的企业搜索引擎,无意间在“聊聊架构”微信公众号里发现了这篇文章,分享给大家. 请点击链接:聊聊基于Lucene的搜索引擎核心技术实践
- C#编写了一个基于Lucene.Net的搜索引擎查询通用工具类:SearchEngineUtil
最近由于工作原因,一直忙于公司的各种项目(大部份都是基于spring cloud的微服务项目),故有一段时间没有与大家分享总结最近的技术研究成果的,其实最近我一直在不断的深入研究学习Spring.Sp ...
- Postgres全文搜索功能
当构建一个Web应用时,经常被要求加上搜索功能.其实有时候我们也不知道我要搜索个啥,反正就是要有这个功能.搜索确实很重要的特性,这也是为什么像Elasticsearch和Solr这样基于Lucene的 ...
- 为什么要用全文搜索引擎:全文搜索引擎 VS 数据库管理系统
正文一:Full Text Search Engines vs. DBMS 发表于2009年 正文二:Elasticsearch - A High-Performance Full-Text Sea ...
- WebGIS中兴趣点简单查询、基于Lucene分词查询的设计和实现
文章版权由作者李晓晖和博客园共有,若转载请于明显处标明出处:http://www.cnblogs.com/naaoveGIS/. 1.前言 兴趣点查询是指:输入框中输入地名.人名等查询信息后,地图上可 ...
随机推荐
- zzuli 2130: hipercijevi 链式前向星+BFS+输入输出外挂
2130: hipercijevi Time Limit: 1 Sec Memory Limit: 128 MB Submit: 595 Solved: 112 SubmitStatusWeb B ...
- UWP 五星好评
var pfn = Package.Current.Id.FamilyName; await Launcher.LaunchUriAsync(new Uri("ms-windows-stor ...
- ElasticSearch 学习记录之 分布式文档存储往ES中存数据和取数据的原理
分布式文档存储 ES分布式特性 屏蔽了分布式系统的复杂性 集群内的原理 垂直扩容和水平扩容 真正的扩容能力是来自于水平扩容–为集群添加更多的节点,并且将负载压力和稳定性分散到这些节点中 ES集群特点 ...
- inotify软件部署及实时同步
声明:博主使用的是CentOS6.9的系统 参考资料: https://github.com/rvoicilas/inotify-tools/wiki http://www.ibm.com/devel ...
- 本地yum仓库搭建及rpm软件包定制
环境内核信息: [root@zabbix-01 ~]# uname -a Linux lodboyedu-01 2.6.32-696.el6.x86_64 #1 SMP Tue Mar 21 19:2 ...
- arguments.callee的临时指向特性
function r(){ alert('BBB'); } var a = { f: function(){ alert('AAA'); arguments.callee = r; } }; 弹出的都 ...
- Python爬虫(十八)_多线程糗事百科案例
多线程糗事百科案例 案例要求参考上一个糗事百科单进程案例:http://www.cnblogs.com/miqi1992/p/8081929.html Queue(队列对象) Queue是python ...
- Spring 面试
1.什么是Spring框架?Spring框架有哪些主要模块? spring框架是一个为Java应用程序的开发提供了综合.广泛的基础性支持的Java平台.Spring帮助开发者解决了开发中基础性的问题, ...
- Android安全专项-利用androguard分析微信
androguard Androguard经常使用API学习1 安装 做 Android 安全測试之前你应该知道的工具 (一) 分析 ./androlyze.py -s进入分析的交互界面 然后运行 a ...
- linux命令的排列、替换与别名
命令的排列; 1.使用";" 命令语法: 命令1;命令2 当运行该命令时,无论命令1是否出错.接下来就运行命令2 2.使用"&&" 命令语法:命 ...