搜索引擎之全文搜索算法功能实现(基于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.前言 兴趣点查询是指:输入框中输入地名.人名等查询信息后,地图上可 ...
随机推荐
- MySQL查看和修改表的存储引擎(转载+加点东西)
1 查看系统支持的存储引擎 show engines; 2 查看表使用的存储引擎 两种方法: a.show table status from YOUR_DB_NAME where name='YOU ...
- HDU 1754 线段树 单点跟新 HDU 1166 敌兵布阵 线段树 区间求和
I Hate It Time Limit: 9000/3000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total ...
- MATLAB中最基本函数plot()的用法
1二维平面图形 1.1基本图形函数 画出一条正弦曲线和一条余弦曲线 1.1.1绘图参数表 y 黄- 实线. 点< 小于号 m 紫: 点线o 圆s 正方形 c 青-. 点划线x 叉号d 菱形 r ...
- 实践作业3:白盒测试----我是如何写测试用例DAY6
一开始接到写白盒测试的任务,我感觉挺难的,因为感觉之前我所想到的都是黑盒测试啊,说到测试系统逻辑,感觉就有些神秘的样子没有思路了,那黑盒和白盒写的到底有啥区别.后来我请教了实验室的一个同学,他虽然还没 ...
- ASP.NET Core Web API下事件驱动型架构的实现(一):一个简单的实现
很长一段时间以来,我都在思考如何在ASP.NET Core的框架下,实现一套完整的事件驱动型架构.这个问题看上去有点大,其实主要目标是为了实现一个基于ASP.NET Core的微服务,它能够非常简单地 ...
- 【技术分析】DowginCw病毒家族解析
作者:钱盾反诈实验室 0x1.背景 近期,钱盾反诈实验室通过钱盾恶意代码智能监测引擎感知并捕获一批恶意应用.由于该批病毒会联网加载"CWAPI"插件,故将其命名为"D ...
- 灵感手环第一步——0.96寸OLED显示实验
这算是我这个系列的第一篇博客吧.首先要解决的就是屏幕显示问题.我选择了目前新兴起的OLED显示模块. OLED(OrganicLightEmittingDiode),中文译作有机发光二极管,目前被广泛 ...
- java 中Map 使用
Map用于保存具有映射关系的数据,Map里保存着两组数据:key和value,它们都可以使任何引用类型的数据,但key不能重复.所以通过指定的key就可以取出对应的value.Map接口定义了如下常用 ...
- LINUX6安装Oracle10g无法启动安装界面解决
***********************************************声明*************************************************** ...
- 【转载】JAVA中综合接口和抽象类实现的一种“抽象接口”
Muscleape个人总结:(这里的抽象接口是指:使用一个抽象类实现一个接口,是两部分结构) 使用一个抽象类直接实现接口,将接口中的方法区分为实现类必须要实现的和选择性实现的,其他需要实现接口的类型通 ...