如何实现Solr自定义评分查询

[size=medium]

(一)背景介绍

大多数时候我们使用lucene/solr/elasticsearch自带的评分查询都是没问题的,当然这也仅仅限于简单的业务或者对搜索排名
不敏感的场景中,假设业务方要求有若干业务因子要干扰到排名,同时还不能放弃框架本身的文本相似度评分,那么应该怎么做呢?
这种场景尤其是在电商类的一些垂直搜索中体现比较明显,比如,新商品加分,口碑好的加分,图片清晰的加分,商品介绍详细的加分,大促的商品加分等等等等,那么如何把众多的业务因素加到的总的评分里面?

(二)实现策略

(1)在索引的时候把众多的业务评分计算提前计算好,存储成一个字段,然后查询的时候根据这个字段排名。
评价:比较简单暴力,适合加权固定,不经常改变评分因素的业务使用,查询性能最高 ,更新,改变,调试评分比较麻烦

(2)在索引的时候把众多的业务评分因子都索引成一个字段,在查询的时候动态获取各个字段评分计算后,加入总的评分从而影响最终的排名。
评价:对动态更改评分支持比较好,查询性能稍差

(3)对于业务的评分因素,动静分离,静态评分因子长期不变的,就全部计算完存储成一个字段,动态的也存储若干字段,最终的评分由静态业务评分+动态业务评分+相似度评分综合得出,从而影响最终的排名。
评价:合理规划评分因素,动静分离,算是业务与技术的一个折中


有关lucene的自定义评分组件,可以参考以前的文章:
[url]http://qindongliang.iteye.com/blog/2008672[/url]

下面来简述下如何在solr中,实现开发自定义评分组件,solr基于lucene,总体来说
与lucene大同小异,需要自己开发几个包装的类即可,在elasticsearch中也是如此,后面有机会,再探讨在elasticsearch中自定义评分的实现

(三)实现方式

(A)通过重写QueryParser实现

1,继承CustomScoreProvider类,重写customScore方法,从DocValues中动态读取评分有关因子,计算后,影响总评分
2,继承CustomScoreQuery类,重写getCustomScoreProvider方法,需要用到1,返回自定义的CustomScoreProvider类
到此,在lucene中就完事了,但是在solr中我们还需要继续
3,继承QParser类,重写parse方法,需要用到2,并在构造方法中,完成一些必须的初始化操作
4,继承QParserPlugin类,重写createParser方法,需要用到3,至此,代码完成
打包项目成一个jar,拷贝至server\solr-webapp\webapp\WEB-INF\lib中
5,在solrconfig.xml中,注册我们写的插件:
[/size]

<queryParser name="myqp" class="com.easy.custom.queryparser.MyQueryParserPlugin">
<lst name="words">
<str name="word">easy_money</str>
<str name="word">easy_count</str>
<str name="word">easy_test</str>
</lst>
</queryParser>

[size=medium]
6, 重启solr,或者reload指定的core
7,打开solr的ui页面,指定defType,测试搜索,如果log不报错,就证明使用成功了
[/size]

[img]http://dl2.iteye.com/upload/attachment/0117/3784/63af55df-80c2-3f02-bacc-3328850475fb.png[/img]

[size=medium]
(B)通过Function Query实现

函数查询一项强大的功能,solr已经自带了
许多的函数,比如数学函数,聚合函数等,详细资料可看官网的wiki资料
[url]https://cwiki.apache.org/confluence/display/solr/Function+Queries[/url]

1,继承ValueSource类,重写getValues方法,并在返回的方法中,完成评分计算逻辑
2,继承ValueSourceParser类,并重写parser方法,返回1定义的类,
建议在parser方法里面,获取ValueSource然后传入自定义的ValueSource类里面复用,
不建议直接从DocValues里面读取,因为基于这个IndexSearch的打开的ValueSource耗费资源更少。至此,代码完成打包项目成一个jar,拷贝至server\solr-webapp\webapp\WEB-INF\lib中
3,在solrconfig.xml中,注册我们的组件:
[/size]

//此处,也可也定义需要传入的参数
<valueSourceParser name="myfunc" class="com.easy.custom.function.MyValueParser" />


[size=medium]
4,打开solr的ui页面进行查询,不报错的话,即查询成功,可以看到和我们第一种方式的结果是一致的
[/size]
[img]http://dl2.iteye.com/upload/attachment/0117/3786/873f910b-3f7e-3b20-97bd-7aa95934ec52.png[/img]
[size=medium]
(四)总结

其实核心功能还是使用lucene实现的,solr/es则是在lucene的基础上提供了强大灵活的插件机制,这样以来,我们就能更容易实现一些我们特殊需求的定制化。

全部代码,已经放在github上:
[url]https://github.com/qindongliang/solr-custom-score[/url]

[/size]

[b][color=green][size=large]
有什么问题可以扫码关注微信公众号:我是攻城师(woshigcs),在后台留言咨询。
技术债不能欠,健康债更不能欠, 求道之路,我们同行。
[/size][/color][/b]
[img]http://dl2.iteye.com/upload/attachment/0104/9948/3214000f-5633-3c17-a3d7-83ebda9aebff.jpg[/img]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值