搜索引擎之全文搜索算法功能实现(基于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.前言 兴趣点查询是指:输入框中输入地名.人名等查询信息后,地图上可 ...
随机推荐
- HDU3792---Twin Prime Conjecture(树状数组)
Twin Prime Conjecture Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Ot ...
- Spark之导出PMML文件(Python)
PMML,全称预言模型标记语言(Predictive Model Markup Language),利用XML描述和存储数据挖掘模型,是一个已经被W3C所接受的标准.PMML是一种基于XML的语言,用 ...
- scapy安装及SCTP包分析
关于Scapy scapy是一个强大的交互式数据包处理程序(使用python编写).它能够伪造或者解码大量的网络协议数据包,能够发送.捕捉.匹配请求和回复包等.它可以很容易地处理一些典型操作,比如端口 ...
- RecyclerView.Adapter优化了吗?
昨天写了一篇「还在用ListView?」讲的内容是RecyclerView的使用技巧以及一些经常使用的开源库.有朋友反馈"我已经在用recyclerview了",那么怎样让它更好用 ...
- HDOJ 4251 The Famous ICPC Team Again
划分树水题..... The Famous ICPC Team Again Time Limit: 30000/15000 MS (Java/Others) Memory Limit: 3276 ...
- 海量日志采集系统flume架构与原理
1.Flume概念 flume是分布式日志收集系统,将各个服务器的数据收集起来并发送到指定地方. Flume是Cloudera提供的一个高可用.高可靠.分布式的海量日志采集.聚合和传输的系统.Flum ...
- Elasticsearch聚合——aggregation
聚合提供了分组并统计数据的能力.理解聚合的最简单的方式是将其粗略地等同为SQL的GROUP BY和SQL聚合函数.在Elasticsearch中,你可以在一个响应中同时返回命中的数据和聚合结果.你可以 ...
- Angular相关命令
1 创建相关 1.1 创建项目 ng new 项目名 -> 创建新项目 ng new 项目名 --skip-install -> 不进行模块安装 ng new 项目名 -si ng ...
- dubbo服务治理中间件,zookeeper注册中心
对传统项目架构进行拆分: 集群概念: 面向服务分布式架构: 服务层提供被注册的对象需要实现序列化接口Serializable: 配置表现层和服务层: 依赖包: 服务层: <!-- 定义dubbo ...
- JavaScript定时器:setTimeout()和setInterval()
1 超时调用setTimeout() 顾名思义,超时调用的意思就是在一段实际之后调用(在执行代码之前要等待多少毫秒) setTimeout()他可以接收两个参数: 1 要执行的代码或函数 2 毫秒(在 ...