原文转载自:

http://qindongliang1922.iteye.com/blog/1953409

高亮功能一直都是全文检索的一项非常优秀的模块,在一个标准的搜索引擎中,高亮的返回命中结果,几乎是必不可少的一项需求,因为通过高亮,我们可以在我们的搜索界面上快速标记出用户的检索关键词,从而减少了用户自己寻找想要的结果,在一定程度上大大提高了用户的体验性和友好度。 



那么,散仙今天就来看下我们在Lucene中,怎么实现高亮,以及高亮的几种实现方式。 

首先散仙还是喜欢老生常谈的来补充下高亮需要的熟悉的基本知识,当然如果你只是需要实现效果,而不关注它的底层API,那么可以忽略此部分,不过散仙还是要友好的提示一下,如果使用过程中出了点小问题,不会API,可是不容易解决的,除非你愿意各种google。 



要使用高亮,首先就得从索引时开始,因为需要高亮的字段,需要准确的获取位置信息,以及一些偏移量,如果信息不准确,那么可能在结果中,就会出现一些莫名其妙的错位,反映到网页上就是标注了不该标注的字,没有标注该标的内容,所以这一点还是需要注意一下,在索引的时候,我们需要使用项向量记录各个token的位置信息,这很简单,代码如下:

 FieldType type=new FieldType(TextField.TYPE_STORED);
type.setStoreTermVectorOffsets(true);//记录相对增量
type.setStoreTermVectorPositions(true);//记录位置信息
type.setStoreTermVectors(true);//存储向量信息
type.freeze();//阻止改动信息
Field field=new Field("字段名", "值", type);//示例

简单说下,TextField的2个枚举变量的意思

变量名 释义
TYPE_NOT_STORED 索引,分词,不存储
TYPE_STORED 索引,分词,存储

由此看来,需要进行高亮的内容,是一定要存储的,可能有一些比较大的文本,会比较占索引空间,从而影响检索性能,当然我们也可以使用外部存储,关系型数据库,nosql什么的都可以,此时,高亮可能就需要做另一些处理了,散仙在下文会介绍。 



下面我们来看下,高亮的需要用到的一些基本的类

释义
SimpleHTMLFormatter 常用的格式化Html标签器,提供一个构造函数传入高亮颜色标签,默认使用黑色
TokenSources 提供静态方法,支持从数据源中获取TokenStream,进行token处理
Highlighter 负责获取匹配上的高亮片段
QueryScorer 对命中结果进行评分操作
Fragmenter 将原始字符串拆分成独立的片段
NullFragmenter 对较短的域进行整体高亮
FastVectorHighlighter 基于快速高亮
Encoder 提供一些实现类,对html文本操作,如,去掉一些特殊匹配符号<,>  and so on,及一些其他的非ASCII特殊字符。


下面我们先来看下散仙的几条测试数据内容:

id:1      name:  中国是一个伟大的国家,我们中国人都是好样的   content:  你好人民
id:2 name: 我们有一个家它的名字是中国 content: 中国的大地,富饶
id:3 name: 我们的中国 content: 如果不在片段中生成一些字段的话
id:4 name: 2014年此时此刻你在做什么的啊 content: 哈哈锄禾日当午
id:5 name: 当你孤单时你会想起谁,你想不想找个人来陪 content: 我永远不孤单啊

1,测试普通高亮的核心代码:

String filed="name";
QueryParser query=new QueryParser(Version.LUCENE_44, filed, new IKAnalyzer(false)); Query q=query.parse("伟大的中国");//测试字段
TopDocs top=searcher.search(q, 100);
QueryScorer score=new QueryScorer(q, filed);//传入评分
SimpleHTMLFormatter fors=new SimpleHTMLFormatter("<span style=\"color:red;\">", "</span>");//定制高亮标签 Highlighter highlighter=new Highlighter(fors,score);//高亮分析器
// highlighter.setMaxDocCharsToAnalyze(1);//设置高亮处理的字符个数
for(ScoreDoc sd:top.scoreDocs){
Document doc=searcher.doc(sd.doc);
String name=doc.get(filed);
TokenStream token=TokenSources.getAnyTokenStream(searcher.getIndexReader(), sd.doc, filed, new IKAnalyzer(true));//获取tokenstream
Fragmenter fragment=new SimpleSpanFragmenter(score);
highlighter.setTextFragmenter(fragment);
String str=highlighter.getBestFragment(token, name);//获取高亮的片段,可以对其数量进行限制 System.out.println("高亮的片段 =====>"+str);
}

输出结果如下 

高亮的片段 =====>中国是一个<span style="color:red;">伟大</span><span style="color:red;">的</span>国家,我们中国人都是好样<span style="color:red;">的</span>
高亮的片段 =====>我们<span style="color:red;">的</span><span style="color:red;">中国</span>
高亮的片段 =====>我们有一个家它<span style="color:red;">的</span>名字是<span style="color:red;">中国</span>

2,快速高亮,FastVectorHighlighter,这个类可能会消耗更多的存储空间,来换取更好的性能,当然除了性能上提升外,它还有一个非常炫的功能,支持多种颜色标记,高亮关键字,除此之外还支持Ngram的域,以及智能合并相邻高亮短语. 

我们来看下散仙快速高亮的3条测试数据:

id:2      name:  中国(China),位于东亚,是一个以华夏文明为主体、中华文化为基础,以汉族为主要种族的统一多民族国家,通用汉语。中国疆域内的各个民族统称为中华民族,龙是中华民族的象征。   content:  中国是世界四大文明古国之一,有着悠久的历史,距今约5000年前,以中原地区为中心开始出现聚落组织进而成国家和朝代,后历经多次演变和朝代更迭,持续时间较长的朝代有夏、商、周、汉、晋、唐、宋、元、明、清等
id:1 name: 中国的自古以来就是一个非常伟大的民族 content: 中国是一个世界人口大国,拥有13亿多的人口.
id:3 name: 没有根的野草,飘忽的命运 content: 谁像你当我宝,什么也做到,旧爱数足一块布,在这一刻写句号,只想跟你终老.

核心代码如下

Query q=query.parse("伟大的中华民族");
TopDocs top=searcher.search(q, 100);
//QueryScorer score=new QueryScorer(q, filed);
//SimpleHTMLFormatter fors=new SimpleHTMLFormatter("<span style=\"color:red;\">", "</span>");//定制高亮标签
//Highlighter highlighter=new Highlighter(fors,score);//高亮分析器
//FastVectorHighlighter fastHighlighter=new FastVectorHighlighter();
FragListBuilder fragListBuilder=new SimpleFragListBuilder();
//注意下面的构造函数里,使用的是颜色数组,用来支持多种颜色高亮
FragmentsBuilder fragmentsBuilder= new ScoreOrderFragmentsBuilder(BaseFragmentsBuilder.COLORED_PRE_TAGS,BaseFragmentsBuilder.COLORED_POST_TAGS); FastVectorHighlighter fastHighlighter2=new FastVectorHighlighter(true, true, fragListBuilder, fragmentsBuilder);
FieldQuery querys=fastHighlighter2.getFieldQuery(q);//reader是传入的流 // highlighter.setMaxDocCharsToAnalyze(1);//设置高亮处理的字符个数
for(ScoreDoc sd:top.scoreDocs){
String snippt=fastHighlighter2.getBestFragment(querys, reader, sd.doc,filed,300);
if(snippt!=null){
System.out.println("高亮的片段是:"+snippt);
}
}

结果如下,注意有多种颜色标识:

高亮的片段是:中国<b style="background:lawngreen">的</b>自古以来就是一个非常<b style="background:yellow">伟大</b><b style="background:lawngreen">的</b>民族
高亮的片段是:中国(China),位于东亚,是一个以华夏文明为主体、中华文化为基础,以汉族为主要种族<b style="background:lawngreen">的</b>统一多民族国家,通用汉语。中国疆域内<b style="background:lawngreen">的</b>各个民族统称为<b style="background:aquamarine">中华民族</b>,龙是<b style="background:aquamarine">中华民族</b><b style="background:lawngreen">的</b>象征。
高亮的片段是:没有根<b style="background:lawngreen">的</b>野草,飘忽<b style="background:lawngreen">的</b>命运

3.下面散仙来着重说一下,高亮的第三种方式,前台高亮,散仙在上文曾提过,基于高亮的字段,必须的存储,否则无法实现高亮标注,当然这种说法,只是对于后台高亮而言的,那么对于大文本情况下,存储到索引里是非常浪费空间的,而且还有可能会影响到检索速度,所以就提出了,第三种方式。 



在前台进行高亮,然后大文本字段,可以存储在外部其他的数据源里面,需要标记时,可以直接根据ID,或者某个字段,读取数据然后通过JS正则在前端替换检索的关键词即可,在这之前需要做的一步就是,使用ajax把检索的关键词,传入后台进行分词,然后将结果返回前台,进行对分词后的数据,进行匹配替换,再加上颜色标记,就可以在前台实现高亮了,这也是前台高亮的实现原理,这种做法,在某些业务场景下,可以大大减少服务器压力,通过客户端减压,以及不用再存储一些向量信息,从而对系统的性能的提高,也是有很大帮助的。 



下面散仙给出一个前台高亮的截图,注意用的是快速高亮的索引。

散仙附上,前台高亮的核心代码

$.ajax({
type :"post",
url: "getContent",
data:"str="+str,
dataType:"json",
async:false,
success:function(msg){
// alert(msg);
$("#div").empty();
$.each(msg, function(i, n) {
var temp="";
for(var i=0;i<shu.length;i++){
if(shu[i]!=""){
n.name=n.name.replace(new RegExp(shu[i],'g'), "<span style=\"color:red;\">"+shu[i]+"</span>");
}
}
$("#div").append("[*]"+n.name+"");
$("#div").append("[*]===============================")});
}
});

至此,有关Lucene的高亮部分的内容,散仙就总结到这里了,如果有什么不足之处,欢迎各位道友指出。大部分场景下,使用普通高亮就可以完成了,当然无论使用那种方式,只要能满足我们的业务就好了,很简单的道理,会抓住老鼠的猫,就是好猫。

Lucene 高亮功能的更多相关文章

  1. 使用prismjs为网站添加代码高亮功能

    prismjs 是一款轻量.可扩展的代码语法高亮库,使用现代化的 Web 标准构建,使用 Prismjs 可以快速为网站添加代码高亮功能,支持超过113中编程语言,还支持多种插件,是简洁.高效的代码高 ...

  2. 简单JavaScript语句实现搜索关键字高亮功能

    高亮功能主要是指对页面中指定区域的指定文字进行高亮显示,也就是背景着色.一般在搜索结果页面会经常用到这个功能. 下面就为大家提供一种解决方案,用javascript实现. 首先在<head> ...

  3. 利用原生JS实现类似浏览器查找高亮功能(转载)

    利用原生JS实现类似浏览器查找高亮功能 在完成 Navify 时,增加一个类似浏览器ctrl+f查找并该高亮的功能,在此进行一点总结: 需求 在.content中有许多.box,需要在.box中找出搜 ...

  4. Lucene 搜索功能

    搜索过程 图解: 主要 API: IndexSearcher:    //所有搜索都通过 IndexSearcher 进行,他们将调用该类中重载的 search() 方法 Query:         ...

  5. Lucene 索引功能

    Lucene 数据建模 基本概念 文档(doc): 文档是 Lucene 索引和搜索的原子单元,文档是一个包含多个域的容器. 域(field): 域包含“真正的”被搜索的内容,每一个域都有一个标识名称 ...

  6. Solr(四)Solr实现简单的类似百度搜索高亮功能-1.配置Ik分词器

    配置Ik分词器 一 效果图 二 实现此功能需要添加分词器,在这里使用比较主流的IK分词器. 1 没有配置IK分词器,用solr自带的text分词它会把一句话分成单个的字. 2 配置IK分词器,的话它会 ...

  7. unity3D HTC VIVE开发-物体高亮功能实现

    在VR开发时,有时需要用到物体高亮的功能.这里使用Highlighting System v3.0.1.unitypackage插件实现. Highlighting System v3.0.1的介绍访 ...

  8. Qt中文本编辑器实现语法高亮功能(Qscitinlla)

    Scintilla是一个免费.跨平台.支持语法高亮的编辑控件.它完整支持源代码的编辑和调试,包括语法高亮.错误指示.代码完成(code completion)和调用提示(call tips).能包含标 ...

  9. Solr(五)Solr实现简单的类似百度搜索高亮功能-2代码

    Solr高亮 一 在配置文件中,配置支持Ik分词器的Field 修改文件: cd /usr/local/tomcat/apache-tomcat-8.5.13/solr_home/Test/conf/ ...

随机推荐

  1. [Linux 小技巧] Ubuntu 14.04 下编译、安装、配置最新开发版 GoldenDict

    1. 背景介绍 GoldenDict 是一款非常优秀的跨平台电子词典软件,支持 StarDict.Babylon 等多种词典.其 PC 版基于 Qt 编写,完全免费.开源且没有广告.GoldenDic ...

  2. Java基础知识强化61:经典查找之 常见查找算法小结

    一.顺序查找 条件:无序或有序队列. 原理:按顺序比较每个元素,直到找到关键字为止. 时间复杂度:O(n) 二.二分查找(折半查找) 条件:有序数组 原理:查找过程从数组的中间元素开始,如果中间元素正 ...

  3. 结合tcpdump命令对traceroute深入分析

    昨天突然被问到traceroute的原理,一时竟也说不出来,有些命令平时虽然经常在用,但实际原理确并不了解,趁这次机会就来梳理一下. traceroute:是网络诊断中,用来分析IP包经过那些路由的命 ...

  4. 关于使用Jsonp做跨域请求

    今天在使用Jsonp做跨域请求的练习时碰上这样一个问题 代码如下 <!DOCTYPE html> <html> <head> <meta charset=&q ...

  5. oracle服务开机自启动

    1.修改oracle系统配置文件::/etc/oratab vi /etc/oratab orcl:/opt/oracle/product/10.2.0/db_1:Y 2.在 /etc/init.d/ ...

  6. JQ简单图片轮播

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  7. DX笔记之五------游戏画面绘图之绘制位图

    本系列文章由zhmxy555编写,转载请注明出处. http://blog.csdn.net/zhmxy555/article/details/7335103 共四步 步骤一:加载位图 步骤二:建立与 ...

  8. 3月22日 html(三)css样式表

    CSS(Cascading Style Sheet,叠层样式表),作用是美化HTML网页. 一.样式表 (一)样式表的分类 1.内联样式表 和HTML联合显示,控制精确,但是可重用性差,冗余较多. 例 ...

  9. dede后台反应特别慢-转

    找到织梦后台管理目录下的/templets/index_body.htm文件 将第25行至第35行部分js代码注释掉. 就这么简单

  10. C语言---volatile(我的工程笔记本)

    一般说来,volatile用在如下的几个地方: 1.中断服务程序中修改的供其它程序检测的变量需要加volatile: 2.多任务环境下各任务间共享的标志应该加volatile: 3.存储器映射的硬件寄 ...