搜索引擎之全文搜索算法功能实现(基于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.前言 兴趣点查询是指:输入框中输入地名.人名等查询信息后,地图上可 ...
随机推荐
- 翻译连载 | 附录 C:函数式编程函数库-《JavaScript轻量级函数式编程》 |《你不知道的JS》姊妹篇
原文地址:Functional-Light-JS 原文作者:Kyle Simpson-<You-Dont-Know-JS>作者 关于译者:这是一个流淌着沪江血液的纯粹工程:认真,是 HTM ...
- javascript算法题判断输入年份是否是闰年
用户输入一个年份,判断这个年是否是闰年.判断闰年条件:① 非整百年数除以4,无余为闰,有余不闰:② 整百年数除以400,无余为闰,有余不闰.比如:2000年,整百数年,就要用②公式,除以400,无余数 ...
- 过渡与动画 - steps调速函数&CSS值与单位之ch
写在前面 上一篇中我们熟悉五种内置的缓动曲线和(三次)贝塞尔曲线,并且基于此完成了缓动效果. 但是如果我们想要实现逐帧动画,基于贝塞尔曲线的调速函数就显得有些无能为力了,因为我们并不需要帧与帧之间的过 ...
- 【NOI2005】维护数列
https://daniu.luogu.org/problem/show?pid=2042 一道伸展树维护数列的很悲伤的题目,共要维护两个标记和两个数列信息,为了维护MAX-SUM还要维护从左端开始的 ...
- 【练习】HTML+CSS
作业要求1 京东首页轮播图,效果如下 <!DOCTYPE html> <html lang="en"> <head> <meta char ...
- 【算法】二叉查找树实现字典API
参考资料 <算法(java)> — — Robert Sedgewick, Kevin Wayne <数据结构> ...
- RT5350的uvc驱动支持yuv格式摄像头成功
请尊重别人的劳动成果 转载请务必注明出处 今天在rt5350的板子上,成功将仅仅支持yuv格式的usb camera摄像头执行了.採用的是mjpeg streamer ,须要libjpeg库支持yuv ...
- hdu 4883 区间选点
昨天比赛的时候没有做出来,本来是想用贪心的,可是贪了好久都没有招, 今天在网上搜了解题报告~好像说这是一类区间选点问题: 有一个好的做法: (1)首先把题目中的时间全转化为分钟,那么区间就在0-144 ...
- RecyclerView高速通用适配Adapter
RecyclerView Adapter 为RecyclerView提供更简单的适配器实现方式,不断更新完好中. Demo视频演示 GitHub地址 博客 使用 BaseViewHolder 的使用 ...
- 【剑指offer】扑克牌的顺子
个大王,2个小王(一副牌原本是54张^_^)...他随机从中抽出了5张牌,想測測自己的手气,看看能不能抽到顺子,假设抽到的话,他决定去买体育彩票,嘿嘿! ."红心A,黑桃3,小王,大王,方片 ...