Solr个性化搜索排序

有不少同学想要代码,把仓库放在这里:

https://bitbucket.org/verycute/niuniusolrcore4.2/src/master/
首先需要改动solr-core模块,这里没有用maven,而是直接导出的方式
https://bitbucket.org/verycute/niuniu-search/src/master/
在改造完solr-core模块后,就支持多段式的搜索框架了,在这里涉及各种排序、queryparser、同义词改造、索引插件等逻辑


A厂的排序方案是添加各种各样的排序链,用于支持各个业务场景下的搜索排序功能,之前我们主搜排序以及筛选页的逻辑非常简单,就是文本相关性+业务分(业务加分+业务扣分),搜索结果干预功能也很直接,这些模块都直接添加在SolrIndexSearcher中,为的是最快的支持搜索排序业务,然后就这么撑了6个月。。。我们发现,用到排序的场景越来越多,比如首页很关键的两个入口:推荐资源和推荐寻车,推荐问题其实完全可以通过搜索召回+排序来进行,这就引入了相应的困难:并没有个性化的搜索排序功能来支持我们做相应的工作,导致我们的推荐和搜索排序策略都非常naive,搜索仅仅是个及格分,而推荐则远不及格,具体原因不分析,我们来看方案的改动

4.2及之前的版本

  1. 定义Component
  2. 定义requestHandler,其中的模块由各个Component组成,例如solr默认的requestHandler select就由query、facet、mlt、highlight、debug以及spellcheck这几个component组成,分别对应各自的功能
  3. QueryComponent调用SolrIndexSearcher的search方法来进行搜索生成结果,所以一开始的思路就是:哪里拿到搜索结果,就在哪里进行我们想要的额外处理:业务加分+搜索结果干预,即resort以及chaos
  4. 正因为搜索无关个性化,所以可以把搜索结果扔到cache中,在新的searcher生成前,下一次搜索过来就会从cache中拿到结果直接返回,而这种缓存机制是完全不适合个性化排序的

如上所述,这种模式不支持从请求中接收额外的参数用户辅助搜索排序,所以也就无法支持推荐相关的逻辑,所以需要改。

*新方案!! *

目前想到的排序特征虽然不算很多,但是也不少了,例如,订单量,用户偏好,用户对资源感冒不感冒,以及资源虽然是今天更新的,但是这个资源的价格是不是不靠谱,以及资源是不是很早很早之前就创建好了,那么现在的价格、颜色等信息其实也已经有了潜在的变动,或者说资源的信息已经不靠谱了。

综上,我们需要参考很多特征来做精排,而这个事情是循序渐进的过程,在优化过程中还需要进行AB实验看看这个特征到底怎么样,用于试探用户的实际业务习惯。所以这里对精排的灵活性提出了非常高的要求,灵活性的含义包括:已有特征的权重调整和新特征的引入,不能引入太多的发布。

所以,参考某宝的排序链,结果solr本身的特性,我开发了我们自己的排序体系:

  1. 新的搜索引入新的QueryComponent,即MyQueryComponent,用于第一步:粗排,即传统意义的布尔检索+filter+sort,用于召回候选集合
    a. 沿用solr自带的缓存机制
    b. 设置粗排截断数量

  2. 引入全新的Component,即MyCustomComponent,顾名思义,用于个性化排序的Component,用于第二步,精排

    a. 排序特征
    开发自己的排序特征,然后在solrconfig.xml中注册特征,该特征才能被排序链使用

    b. 排序链
    定义排序链,排序链由不同的已注册特征以及对应的权重构成,精排分对这些的特征进行加权求和

    c. 搜索结果干预
    chaos参数,引入新的solr url参数chaos_field,同时去除chaos为负数的情况(根据user_id或者hashkey来剔除某些搜索结果),因为该情况需要我们对搜索进行妥协,而且这个功能并不是很关键,或者说并不是很合理

缓存

solr本身有着较为完善的缓存机制,但是当我们把整个体系设计成个性化模式时,通用的缓存模式已经不再适用了,即A君搜索X5和B君搜索X5完全是奔着宝马和东南这两个不同的品牌去的,你缓存宝马的搜索结果给B君那就是灾难,所以我们这里只能缓存粗排结果。即只有精排阶段会涉及到个性化的信息,而粗排阶段的统一召回完全是根据通用信息和属性来的,所以缓存粗排结果是一个比较合理的选择。

于是由于4.2版本引入的chaos、resort等用户计算缓存key的模块就可以移除了。

样例

solrconfig.xml配置:

注册自定义的SearchComponent

<searchComponent name="niuniu_query" class="org.apache.solr.handler.component.MyQueryComponent"/>
<searchComponent name="niuniu_custom" class="com.niuniu.rankings.MyCustomComponent"/>
<searchComponent name="niuniu_debug" class="com.niuniu.rankings.NiuniuCustomDebugComponent"/>
  1. niuniu_query类似常规solr的QueryComponent,我们进行了一定的改动,让该模块成为粗排模块,为下层的niuniu_custom个性化精排模块提供粗排截断后的结果;
  2. niuniu_custom对应的是精排模块,这一阶段的工作就是拿到粗排阶段的结果,使用字段(从DocValue中获取)以及http请求带过来的个性化参数,通过排序链为各个进入这一阶段的结果进行重打分,然后根据最终分数做稳定的排序,然后再做重排序;
  3. 为了我们debug方便查看各个特征和模块的分数情况,我们引入了niuniu_debug模块,是参照A厂的哆啦A梦平台搞的。。

定义requestHandler

<requestHandler name="/select" class="solr.SearchHandler"><arr name="components"><str>niuniu_query</str><str>niuniu_custom</str><str>niuniu_debug</str></arr></requestHandler>

注册排序时要用的特征

  <featureFactory name="search_feature" class="com.niuniu.search.features.NiuniuSearchFeatureFactory" ><str name="fields">search_score_1</str><str name="weights">1</str></featureFactory><featureFactory name="new_resource_feature" class="com.niuniu.search.features.NiuniuNewResourceFeatureFactory" ><str name="fields">created_at_ms</str></featureFactory>

根据不同的特征,定义不同的排序链

其中各个权重用于不同特征的加权求和,分数最终会作用于精排阶段的排序依据

  <niuniuSortChain name="wlsort1" class="com.niuniu.rankings.NiuniuRankingServiceChain" ><str name="features">search_feature</str><str name="weights">1</str></niuniuSortChain><niuniuSortChain name="wlsort2" class="com.niuniu.rankings.NiuniuRankingServiceChain" ><str name="features">new_search_feature, new_resource_feature</str><str name="weights">1,2</str></niuniuSortChain>

对于一个工程师来说,如果想开发排序模块,只要开发排序特征代码,然后在solrconfig.xml中注册该特征并且加入到排序链中就可以生效了,外部代码模块对他来说就当黑盒子使用即可。

solr最终搜索串如下:

http://xxx/solr/production/select?q=c200&wt=json&defType=niuniuparser&chaos=4&sort_chain=wlsort1&chaos_field=user_id&
fl=id,score&start=0&sort=updated_at+desc,+created_at+desc&resort=true&rows=20&
fq=(post_type_i:0+OR+post_type_i:2)+AND+post_status_i:1&userinfo=xxx10.8|xxx0.64|xxx^0.15

可以看到我们沿用了solr本身的参数体系,然后多加了其他参数的解析:

  1. chaos用于搜索最终结果的处理(即重排序),例如相同卖家的资源不能连续出现等

  2. chaos_field告知MyCustomComponent哪个字段用于做重排序

  3. sort_chain即使用哪个排序链进行此次搜索,不同的排序链对应着不同的排序方案或者排序加权方案,这种设置一是为了灵活性二是为了做AB实验

  4. resort告知MyCustomComponent这次搜索需要走精排逻辑,这样如果不带resort=true的话默认就是粗排方案,但是可以进行重排序,不带该参数时sort_chain也失效

  5. userinfo用于传递用户的信息,一般这些信息都是从redis中获取,传到MyCustomComponent中,不同的特征在parseUserInfo阶段专门读取自己需要的信息

  6. defType=niuniuparser参考之前的文章

总结

这里只是把基本的构造一个类似某哦宝的粗排+精排+重排序的大方案介绍了一下,至于具体的细节还有很多的值得思考的地方,在很多所谓的细枝末节上其实花的功夫非常多,例如在精排阶段读取doc的字段,怎么读?之前是使用SolrDocument来读取,也没有在意schema.xml中的DocValue属性,发现效率很低,后来又去从fieldCache读取,效率提高很多但是内存占用较高,最后使用DocValue,即所谓的正排字段,效率高且内存占用率低,才能搭起来一个平均搜索时长在6ms左右的个性化搜索框架,当然这和我们用的精排特征有关,如果你有海量特征或者使用树模型来在精排阶段打分,就会较为耗时了

后续还会在新写一些文章代码细节上进行补充,并且给出一些代码的sample这样让看客们尽量少走弯路。

有问题可以私信或者发我邮件

Solr完整个性化搜索排序方案相关推荐

  1. 阿里飞猪个性化搜索排序探索实践

    导读:旅行类商品 ( 如机票.火车票.汽车票 ) 相对实物电商更加标品,用户决策因素更加单一,而行业内大多基于简单规则排序,如时间.价格或业务逻辑加权,难以满足用户的个性化出行需求.飞猪在过去一段时间 ...

  2. 标签权重在个性化搜索排序中的最佳实践

    个性化搜索需要满足: • 具备较强的语义理解能力,精准命中搜索需求: • 满足搜索关键词和内容的多样性特点,可根据用户行为优化排序,实现个性化搜索: 例如: a. 搜索"吃鸡",可 ...

  3. 知乎搜索排序模型的演进

    公众号:系统之神与我同在 导读: 搜索, 是用户获取信息, 找答案最方便快捷的方式 .一次用户搜索会经历 Query 解析 .召回 .排序多个环节, 排序作为最后整个过程一环, 对用户的体验 有最直接 ...

  4. 京东亿级商品搜索排序规则技术全面公开

    作为京东商家不需要读懂搜索规则的数据处理,2019年算法的变革将继续加大力度,毕竟搜索的流量依旧是京东商家主要的流量获取入口,今天的文章着重解密京东搜索技术,帮助商家更好理解. 助教:鹿鸣  |  作 ...

  5. 个性化搜索的介绍,推荐和搜索的强强结合

    点击上方"AI公园",关注公众号,选择加"星标"或"置顶" 作者:Pavel Kordík 编译:ronghuaiyang 导读 一般来说, ...

  6. 【算法原理篇】个性化搜索的介绍,推荐和搜索的强强结合

    作者:Pavel Kordík 编译:ronghuaiyang 导读 一般来说,搜索是非个性化的,不过如果和推荐系统组合起来,也会有意想不到的效果. 寻找正确的信息总是很困难的.在不久之前,文档还是存 ...

  7. Airbnb个性化搜索服务架构

    导语:业务快速增长给搜索带来什么样的挑战?针对类似场景如何设计通用的平台?本文详细讲述Airbnb大型搜索服务的演进之路. 去年,Airbnb到了需要可扩展.分布式存储系统的时候了.例如,搜索个性化数 ...

  8. 如何快速实现精准的个性化搜索服务

    简介: 用户行为数据如何实时的应用在搜索服务中那? 怎样在1天内就可实现[精准的个性化搜索系统]搭建那? 今天小编将通过[阿里云开放搜索]中的三大"个性化搜索算法模型"给大家详细介 ...

  9. 劈开迷雾:蘑菇街搜索架构及搜索排序实践

    2017-04-03 23:48 前言 蘑菇街的愿景是让一半人类更幸福,而让每位女性用户能便捷的找到心仪的商品则是搜索系统的愿景.作为重要的流量入口,搜索系统一直承担着关键的职责:优化商家流量分配和提 ...

  10. 劈开迷雾,蘑菇街电商搜索架构及搜索排序实现

    劈开迷雾,蘑菇街电商搜索架构及搜索排序实现 前言 蘑菇街的愿景是让一半人类更幸福,而让每位女性用户能便捷的找到心仪的商品则是搜索系统的愿景.作为重要的流量入口,搜索系统一直承担着关键的职责:优化商家流 ...

最新文章

  1. delphi使用outputdebugstring调试程序和写系统日志
  2. 领先微软技术咨询公司招聘技术人员
  3. CSDN下载频道2014年11月4日本-5日常维护公告
  4. 689D Magic Odd Square 奇数幻方
  5. Git 常用命令(二)
  6. 系统微服务签发token
  7. C# Types Type Members
  8. Net-snmp开发流程:MG-SOFT套件生成C语言snmp set/get代码
  9. 请确保此代码文件中定义的类与“inherits”属性匹配.并且该类扩展的基类(例如 Page 或 UserControl)是正确...
  10. 时间函数strtotime
  11. KMS Server相关资料
  12. Python、Lua和Ruby——脚本大P.K.
  13. 《机器学习实战》学习笔记第二章 —— K-近邻算法
  14. 计算机识别键盘流程,电脑键盘拼音打字操作过程
  15. 新书推荐 |《深入浅出Serverless:技术原理与应用实践》
  16. MATLA 复制文件到指定文件夹
  17. ios 开发 flurry 资料
  18. 2020牛客暑期多校训练营(第九场) The Escape Plan of Groundhog
  19. 【邻接矩阵乘法】沼泽鳄鱼
  20. ClickHouse在各大厂的最佳实践

热门文章

  1. 活动|域名转入专场活动
  2. CentOS上安装 Docker-CE以及Docker 加速器配置
  3. 非常全面的IReport的使用
  4. 苹果开发者后台,修改付费app中银行账户信息时注意
  5. 15个快速学习苹果Swift编程语言的入门教程
  6. ​大连商务英百家外语英语六级水平,适合报考BEC中级还是高级
  7. android常用字体代码,Android TextView设置字体风格多种组合
  8. Docker - Docker Image及Image命令详解
  9. 如何申请邮件安全证书(S/MIME)实现邮件加密和数字签名
  10. 程序员每天自动填写周报日报工时脚本完整脚本(附源码)