设为首页 收藏本站
查看: 1107|回复: 0

[经验分享] 六、Solr高亮与Field权重

[复制链接]

尚未签到

发表于 2015-7-16 12:04:09 | 显示全部楼层 |阅读模式
Solr高亮
  原理
  做搜索时,高亮是很常见的需求,那么Solr肯定也为高亮提供了支持。先解释下Solr高亮的原理,在我们设置了需要高亮显示的Field之后,查询得到的返回结果会多出来下面的内容:



"highlighting": {
"519": {
"Artist_Name": [
"周杰伦"
]
}
}
  
  其实就是多了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(""); //标记,高亮关键字前缀
songQuery.setHighlightSimplePost("");//后缀
  
  2.solrConfig.xml配置:






explicit
10
text
true
content
50
<font color="red>
</font>


  
  详细的RequestHandler配置请参看博客:五、SolrJ、Request Handler
  其实这两种配置并没有本质上的区别。我个人习惯使用SolrJ配置。
  
  解析
  获取highlighting是非常简单的,一条语句搞定:
  



Map tempMap = response.getHighlighting();
  
  相信大家也注意到了,虽然接受结果简单,但是如果想遍历就比较复杂了,因为接受到的结果是嵌套了很多层的类型Map
  那么我这边把我解析的方法分享下:
  



Map tempMap = songHighlight.getHighlighting();
for(Map.Entry entry : tempMap.entrySet()) {
if(Integer.parseInt(entry.getKey()) == song.getSong_SongID()) {
for(Map.Entry 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("");//后缀
  然后再用split("@")分隔出不同的Song_SingerName,但是这样就会有一个问题,就是我不知道高亮的歌手到底是哪一个歌手,所以这个时候,我还需要从分割后的String[]中提取所有的中文字符,比对后,存入另一个变量,最后再用"/"替换掉"@"。



Solr权重
  概念
  Solr底层依然用的是Lucene的权重算法,也就是通过一个公式计算每个Documents的得分,然后按得分高低排序,公式如下:
DSC0000.png
  简单解释下这个公式中包含的一些因子:
  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的优先显示、最近上传的优先显示、清晰度高的优先显示。

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-87286-1-1.html 上篇帖子: Lucene / Solr 开发经验 下篇帖子: solr+facet学习笔记
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表