Solr高亮与Field权重

 

Solr高亮

原理

做搜索时,高亮是很常见的需求,那么Solr肯定也为高亮提供了支持。先解释下Solr高亮的原理,在我们设置了需要高亮显示的Field之后,查询得到的返回结果会多出来下面的内容:

"highlighting": {

"519": {

"Artist_Name": [

"<em>周杰伦</em>"

]
}
}

其实就是多了highlighting的字段,并没有改变原来返回的字段内容。

Json串是使用 Unique Field :{高亮显示的内容}的形式。

SolrJ有三种高亮类型:

如果要对某field做高亮显示,必须对该field设置stored=true

Standard Highlighter,根据查询的docIdSet,获取Documents,并获取当前document的需要高亮的field的value,根据query的term和该field的value做匹配算法
FastVector Highlighter,效率比普通的高亮显示要高;需要定义termvector(占用空间和IO),包括position和offset,根据query term的termvector到field value中做快速的定位标记,进而实现快速的高亮显示
Postings Highlighter,由于高亮显示需要对field设置为store=true,所有对于单节点数据量比较大并且该字段比较大的话,会消耗大量的IO操作,那么可以把该字段存储在另外的地方,比如Hbase,在外部做高亮显示的匹配。

其中推荐使用的是Standard Highlighter,下面也是针对Standard Highlighter,

配置

下面介绍两种配置方式:

  1.SolrJ配置:

//设置高亮
songQuery.setHighlight(true); // 开启高亮组件或用query.setParam("hl", "true"); songQuery.addHighlightField("Song_Name,Song_SingerName");// 高亮字段
songQuery.set("hl.highlightMultiTerm","true");//启用多字段高亮
songQuery.setHighlightSimplePre("<font style=\"color:#A7D043;font-weight:bold;\">"); //标记,高亮关键字前缀
songQuery.setHighlightSimplePost("</font>");//后缀

  2.solrConfig.xml配置:

<requestHandler name="search" class="solr.SearchHandler" default="true">
<!-- default values for query parameters can be specified, these
will be overridden by parameters in the request
-->
<lst name="defaults">
<str name="echoParams">explicit</str>
<int name="rows">10</int>
<str name="df">text</str>
<str name="hl">true</str>
<str name="hl.fl">content</str>
<str name="f.name.hl.fragsize">50</str>
<str name="hl.simple.pre">&lt;font color=&quot;red&gt;</str>
<str name="hl.simple.post">&lt;/font&gt;</str>
</lst>
</requestHandler>

详细的RequestHandler配置请参看博客:五、SolrJ、Request Handler

其实这两种配置并没有本质上的区别。我个人习惯使用SolrJ配置。

解析

获取highlighting是非常简单的,一条语句搞定:

Map<String,Map<String,List<String>>> tempMap = response.getHighlighting();

相信大家也注意到了,虽然接受结果简单,但是如果想遍历就比较复杂了,因为接受到的结果是嵌套了很多层的类型Map<String,Map<String,List<String>>>

那么我这边把我解析的方法分享下:

Map<String,Map<String,List<String>>> tempMap = songHighlight.getHighlighting();
for(Map.Entry<String, Map<String,List<String>>> entry : tempMap.entrySet()) {
if(Integer.parseInt(entry.getKey()) == song.getSong_SongID()) { for(Map.Entry<String, List<String>> entryLayer2 : entry.getValue().entrySet()) {
if(null != entryLayer2.getKey() && "Song_Name".equals(entryLayer2.getKey())) {
//your Operation
}
if(null != entryLayer2.getKey() && "Song_SingerName".equals(entryLayer2.getKey())) {
//your Operation
}
}
}
}

这个方法比Iterator和foreach效率稍高。

我设置了两个字段需要高亮,所以在循环中判断了高亮是属于哪个字段,之后进行相应的操作。

因为我做的时候,一首歌可能有几个Song_SingerName,在数据库中用"/"分隔,所以这种情况更加复杂,我首先是把后缀中的/换成了出现概率很小的@

songQuery.setHighlightSimplePost("<@font>");//后缀

然后再用split("@")分隔出不同的Song_SingerName,但是这样就会有一个问题,就是我不知道高亮的歌手到底是哪一个歌手,所以这个时候,我还需要从分割后的String[]中提取所有的中文字符,比对后,存入另一个变量,最后再用"/"替换掉"@"。

Solr权重

概念

Solr底层依然用的是Lucene的权重算法,也就是通过一个公式计算每个Documents的得分,然后按得分高低排序,公式如下:

简单解释下这个公式中包含的一些因子:

Tf:Term frequency,就是条目出现的次数。

Idf: Inverse document frequency,就是用来描述在一个搜索关键字中,不同字词的稀有程度。比如搜索The Cat in the Hat,那么很明显The和in远没有Cat和Hat重要。

Boosting:这个使我们设置权重的重点,比如搜索歌手名,那么在一个document中还有歌手的ID、歌曲的清晰度、歌曲上传时间,而boosting是不同的Filed有不同权重,之后根据公式计算得分。所以可以看到,我们并不能直接影响solr搜索结果的排序,需要改变权重,进而改变不同Document的得分,从而影响排序。

其中还有很多因子和公式的解释,有兴趣的同学可以参考Solr in action这本书,里面有比较详细的解释。

因为我们只需简单的根据某一Filed的权重影响结果的排序,所以我们需要改变Document的Boosting,那么就需要用到Dismax,Dismax是一个查询解析器(Query parser),查询解析器的概念就是提供了一系列查询的参数,一旦我们在查询url中设置了相应的参数,那么查询解析器将会解析查询信息,从而得到搜索结果,其实完全也可以把查询解析器理解为一个Api,就是提供了相应的方法,我们设置,之后Solr根据我们设置的参数进行查询,只不过不同的Query Parser提供了不同的参数而已。

一共提供了三种Query Parser

Standard:最常用的,并且是默认

Dismax:

Extended Dismax

功能从上至下是逐渐递增的,在大部分情况下,Standard已经可以完全满足需求,但是因为要使用权重排序,那么需要用到Dismax,具体提供的参数请查看wiki:

https://cwiki.apache.org/confluence/display/solr/The+Standard+Query+Parser

那么首先需要设置Query Parser为Dismax:

songQuery.set("defType","dismax");

之后设置需要查询的Field:

songQuery.set("qf","Song_Name^2 Song_SingerName^0.2");

比如我这里就需要根据用户输入的关键字查询歌手名和歌曲名,之后返回这两个Field命中的结果、多个Query Filed中可以设置不同的权重,比如Song_Name的权重就为2,必须注意,在Solr权重的设置中,所有权重标准为1,意思是当权重设置大于1时,代表这个字段的权重变大,如果权重设置小于1并且大于0的时候,代表这个字段权重变小。

之后设置其它Field的权重:

songQuery.set("bf", "sum(div(Song_Quality,0.01),if(exists(Song_FileMV),20000,0),recip(ms(NOW,Song_CreateTimeForNew),1,10000,1))");

这里面用到了很多Function Query,比如div,代表相除、exists代表如果Song_FileMV如果不为空那么设置它的权重为20000,为空则为0。记住最后要sum起来,因为从上面的公式可以看出来,boosting是一个变量,所以最好要有一个和值。相关的函数请参考wiki:

http://wiki.apache.org/solr/FunctionQuery

这样搜索结果就会按照有MV的优先显示、最近上传的优先显示、清晰度高的优先显示。

作者<ahref="http: www.cnblogs.com="" edwinchen="" "="" target"_blank"="">瞪着太阳的乌鸦

 
分类: Solr

Solr高亮与Field权重的更多相关文章

  1. 六、Solr高亮与Field权重

    Solr高亮 原理 做搜索时,高亮是很常见的需求,那么Solr肯定也为高亮提供了支持.先解释下Solr高亮的原理,在我们设置了需要高亮显示的Field之后,查询得到的返回结果会多出来下面的内容: &q ...

  2. solr 高亮配置

    solrj中配置: 两种高亮开启设置 // solrParams.setHighlight(true); solrParams.setParam("hl", "true& ...

  3. solr schema.xml Field属性详解

    <field name="id" type="string" indexed="true" stored="true&quo ...

  4. solr高亮设置以及摘要

    高亮显示 public SolrDocumentList query(String str) { SolrQuery query = new SolrQuery(str); //设置高亮,以下两种方式 ...

  5. solr 基本命令二(权重查找)

    package zr.com.solr.utils; import java.io.IOException; import java.util.HashMap; import java.util.Li ...

  6. solr高亮及摘要

    修改了原文的一点内容:原文地址为:http://www.cnblogs.com/rainbowzc/p/3680343.html 高亮显示 两种方法: 1.在程序里通过设置query返回高亮信息 pu ...

  7. Solr高亮详解

    hl.fl: 用空格或逗号隔开的字段列表.要启用某个字段的highlight功能,就得保证该字段在schema中是stored.如果该参数未被给出,那么就会高亮默认字段 standard handle ...

  8. Solr字段类型field type的定义

    摘要: Solr的字段类型定义了Solr如何解析字段数据并将数据检索出来,了解Solr的字段类型定义有助于更好的配置与使用Solr. 字段类型的定义 字段类型的定义主要包含如下四个方面的信息: 名称 ...

  9. 启动Solr时报 _version_ field must exist in schema 错误的解决方法

    Solr启动时报 org.apache.solr.common.SolrException:org.apache.solr.common.SolrException: Unable to use up ...

随机推荐

  1. 远程访问mysql(转)

    GRANT ALL PRIVILEGES ON *.* TO '<username>'@'<remote addr or %(for all ip addr)>'IDENTIF ...

  2. 推荐系统相关算法:SVD

    假如要预测Zero君对一部电影M的评分,而手上只有Zero君对若干部电影的评分和风炎君对若干部电影的评分(包含M的评分).那么能预测出Zero君对M的评分吗?答案显然是能.最简单的方法就是直接将预测分 ...

  3. PHP接口和抽象类的区别

    原文引自: http://blog.csdn.net/sunlylorn/article/details/6124319 一. 抽象类abstract class 1 .抽象类是指在 class 前加 ...

  4. ORACLE 动态注册和静态注册的区别(转)

    1, oracle 10g 用netca方式建立的都默认为动态注册方式2,如果想改为静态注册的方式则在listener.ora 中加入如下内容即可 SID_LIST_LISTENER = (SID_L ...

  5. Sharepoint 2013 左右&quot;SPChange&quot;一个简短的引论

    于SharePoint于,我们经常需要获得这些更改项目,竟api为我们提供SPChange物.下列,在通过我们的目录资料这一目标. 1.创建测试列表,名字叫做"SPChangeItems&q ...

  6. Jquery学习(三)选择

    1.Jquery最重要的是选择. 学习要点:        1.简单选择器        2.进阶选择器        3.高级选择器 ①简单选择器. 最简单的也就是最经常使用的,最经常使用的一般也是 ...

  7. iis配置网址(主机名)

    一直以来,常常弄不成功关于网址的问题. 今天查了下资料 首先,找到你的文件:C:\Windows\System32\drivers\etc的hosts文件,直接用记事本打开 # Copyright ( ...

  8. Web字体@font-face对于中文字体的使用

    今天算是刚开始玩博客园..感觉很新鲜在首页 上看到了一个博客http://www.cnblogs.com/liuminghai/p/4238256.html是关于web文字的,挺不错 但是B/S的前端 ...

  9. 【MySQL案件】mysql登录-S失败

    1.1.1. mysql登录mysql时间,-S参数失效 [环境的叙述性说明] mysql5.5.14 [问题叙述性说明] 配置多个实例 实例1 实例2 datadir /home/mysql_330 ...

  10. java_log4j----java 日志管理

    log4j 有三个主要组件: 类别Loggers------消息类型和优先级 附加目的地Appenders-------在哪里报告消息 布局Layouts------控制如何格式化消息 这三个组件共同 ...