IT技术博客大学习 共学习 共进步

我感受到的排序机制参考

淘宝网综合业务平台团队博客 2012-09-20 13:43:29 浏览 2,362 次
人们总觉得这个搜索领域很多秘密,门槛如此之高,如此神秘。其实不是那么回事。基本的原理、流程理解了。就可以做到心中不慌。先了解机制,细节和具体才是难点,不要被难在开始!下面就结合实际经验积累,给出参考信息。不针对任何排序模型,只描述粗略内容。具体场景具体怎么高,私下交流。
提示:排序规则务必公开,否则会有非常多的诟病、诟骂。不要以为你的排序是机密,
包括自己的开发成员都含糊其辞的,这样只会增加排序的神秘性、恶意去钻空子等。
完全公开排序细则,明确排序导向什么、打击什么,只是一些得分因子、权重需要慎重,
是否全面公开,而排序算法是完全可以公开的。即使不公开,一帮外面的专业seo
很快就找到规律的,那时候就非常被动了。
案例1: **********

    

排序理念

对与应用涉及面比较广,并且影响交易或者第三方切身利益的应用。建议应用方:
公开排序指导思想或者排序的整体理念、排序的重要因子、可能作弊的情况。
在执行中,改版或者调整排序,提前公布变动前后可能的影响、务必收集匿名反馈的作弊信息和公布作弊处理情况。
排序细节无需公开,但是对排序有重要影响的因子应该公开,并且排序结果是可以解释清楚的!

    

反作弊

搜索作弊从搜索上线第一天起就伴随着每一次搜索优化而存在。不保证没有任何的作弊空间,只是期待对常规的、明显的作弊加以
杜绝。下面做的描述,是很基本的场景,如果开发人员知道后,不加以控制,反而利用起来赚外快,那真实背信弃义了啊。
终搜这边会不定期抽查,发现不纠正的会邮件通报。
反作弊应该从一开始就着手防范,而不是等问题严重了才下手。作弊是从一开始就执行,逐步的深入。
反作弊应该是产品规划中,不可用缺少的一部分。

    作弊之一:关键词堆积。

例如:商品描述中重复文字。例如女装女装女装女装、T恤T恤T恤T恤、韩版韩版韩版等。
例如:用户登录注册用户名:丽君丽君丽君  小五小五小五小五 等
例如:描写所在地有很多个,并且貌似没有多大关系。例如 杭州 上海 南京啊
例如:商品授权或者质检等,本来没通过,不知怎么的进入了商品授权、质检行列。这个隐形作弊!
例如:价格区间,排序相关的那个字段是一种价格,和实际成交的价格两马事。可能排序的是打折后的价格、最低的一个商品价格
、最小尺寸的那个价格。总之这个价格要控制,既包括入索引,也包括输入查询的时候。
 通常:关键词堆积,就是那些热点词。执行这些作弊的也是那些相对老的客户,或者一些大卖家。
抽查的时候可以定点执行。那些由用户可以输入的地方就是入口。

    作弊之二: 频繁更新

例如:频繁更新上架、下架时间,使得按时间排序的时候,活得靠前展示机会。而实际上商品压的没改啥,就是执行一个上架、
下架操作而已。对应这个场景,需要对变更引入控制逻辑,不同的变更贡献不同的分值。谈化单一维度值对排序的直接影响。
对于更新的数据,后台应该加以监控。更新表现了很多信息,不仅是活跃状态,成长趋势,也夹着这非常规行为。需要对
变更做追踪统计。

    作弊之三:内容与描写不一致

例如:上传图片和描述不一致,图片分离和图片标题不一致。
例如:标题说韩版,实际不是什么韩版信息,只是店铺中有韩版的商品,不代表全部商品都是韩版,导致商品描述
中渐渐商品统一描述,明显不符合实际。
例如:淘金币、积分、打折等,只有部分商品有效,结果泛滥到店铺所有商品,明显不对。
例如:本来属于活动区域,结果堆积广告信息。
例如:运费说明含糊不清,最低运费有条件的不说明,多少价位运费不等同全部信息。误导人!
通常,抽查这些信息,就是选取流行的品牌名称、畅销、热销名称、活动名称等。不排除从量子产品那边获取信息,
然后应用到其他产品中来。对于敏感资源、热点词、热销、畅销、活动等区域,要求开发、质检多多抽查关注了。
当前还没有统一的源数据review视图,不能直接展示源数据的聚合特性和峰值特性,后续会加强这块服务。
也希望与应用一道推进这块服务。降低不一致性。

    作弊之四:各种刷

这个各种刷,搜索基本没折。只能靠应用中有这个意识,从多个维度来排序,降低风险。
有刷点击、刷积分、刷成交、刷交易、刷评价、刷。。。。
需要应用对参入排序的维度做监控展示,任何突发、聚集的变化应该引起关注。

    

排序的选择

    

应用类型

有针对内部使用的系统、有针对外部使用的系统。理解为后台应用和线上应用
有全文匹配应用、有标签点击查询应用,理解为主动搜索和被动搜索
有查询直接关联交易的应用、有查询只是展示信息,不会直接关联交易的应用。理解为交易型和社区型
针对不同的场景,查询逻辑、查询条件构造、数据来源、数据更新频率等都各不相同。需要具体应用具体对待。

    

排序类型

粗略将排序定格为:默认排序(默认的文本相性排序或者扩展的相关性排序)+ 单因子排序
单因子排序这里指一个或多个维度的某个值来排序。默认排序可以是文本相关性+离线计算的得分模型计算得分。
下面针对单因子排序做说明,这里面最容易出现作弊。具体场景问题可以反馈给***!

    (1)时间排序

例如对查询命中的文档,按文档时间域域值来排序,
时间先后决定了排序靠前或者靠后。这里也存在故意更新的,使得排序尽可能靠前。
对策:这里需要运营、开发综合分析具体场景,决定是否使用这个排序维度,是否有影响公平性
案例分析
  现有的更新时间排序没什么用,供应商可能为了排序靠前,经常更新,想按发布时间排序,但目前没有(打小怪兽ing,实际有
没找到,还有列表文案一直是更新时间)
a)这个频繁更新(导致故意频繁更新,本质没更新) 为获取排序靠前-----这个有作弊嫌疑。
b)当前默认排序 那边有新的算法
c)按单维度排序 例如时间,建议加以其他限制,而不是纯粹的时间
(例如更新频率等、更新那一块有对应的贡献值,简单的改动或许不应该对排序有影响,更多细节要业务去确定)
d)版本发布前,对所有排序有变动的地方,做书面澄清,明确告诉平台用户:排序导向什么、排序的总体规则、和任何排序结果
是可以解释的

    (2)按价格排序

对命中文档,按照价格高低或者价格区间来排序,这里也存在故意调整价格,使得排序尽可能靠前
  对策:价格排序只用在用户主动搜索时,勾选的条件而不引入默认排序中。在数据入口时,严格控制价格区间。
运营人员和开发人员严格把关,一些假数据不进入dump中心。另外,对卖家的最近3个月价格做展示,
并提示用户关注卖家最近价格动态

    (3)按人气排序

人气的定义可以是点击量、关注量、使用量、成交量、评价量等等。这里也存在作弊。例如点击量,有可能就是雇佣人或者
机器在刷点击、刷关注、刷使用--伪操作,看起来有使用,不见得真正使用、成交量就是速卖速退、虚假评价
对策:前端页面务必加强过滤,可以联系安全部门负责scm的同学,对与明显刷机的要严惩不待。另外,对这个维度的增长
做历史统计,对一些异常增长的数据加以报警,然后人肉分析是否正常。就是对于按具体维度排序的这个项做监控!
也可以每天遍历一下数据库或者索引,将每天的信息统计,然后按周、月统计比较。

    (4)按地域排序

按地域排序,就是对一些描述文本加强人工或者机器逻辑的限制,防止地域信息冗余。
对策:地域文本做逻辑判断,语义上的和词条数目上的控制。

    (5)按得分排序

按照某个属性的得分排序,得分的高低直接表现在页面上。这个存在作弊,就是得分不真实或者一段时间得分不真实,
追求短时或者活动期瞬时的资源位。
对策:得分不是直接得分,而是某几个维度的综合得分,而维度以及维度联合计算应该公开,从而照顾更多场景。
例如新上线、服务好、发货快、质量好、评价好、创新型强等。各个维度贡献值,需要对历史数据统计分析,而不是
拍怕脑袋随便定义!

    (6)按颜色、尺码、供应商等排序

这个作弊比较少,因为颜色、供应商啥的作弊后,只会影响服务提供者。

    

排序实现

排序可以在dump的时候,事先将各个文档的域或者某些关键词的权重单独或者综合计算为一个得分。排序按这个域值执行!
或者默认的文本相性排序或者按某个直接的域值排序。也可以动态的将特殊对待的得分激励写在查询串中。

同一个应用中,有多个查询场景,可以不同查询场景对应不同查询的排序策略,而不是统一排序策略。例如搜商品和搜商家
提供两种排序策略。
如果按照某个维度排序,结果表现另外维度的聚合特性。例如搜商品都是集中的几个商家,那么需要对排序混合或者group
或者调整之前的排序,避免这种聚集现象。
对应一些排行榜,建议多个维度展示。既可以默认展示1到3个维度,也可以用户勾选多个维度联合展示
例如 展示价格的同时,将成交量、评价、使用量等重要因素的排序也带上
或者每隔1分钟,更换一种排行榜,从而将不同维度的排行榜均等、全面展示,而不是固定展示。
对应默认排序多关键词的,关键词直接的AND OR可以定制化,从而保证默认结果很友好(没有最优只有近似最优)

    

排序更新

建议每1个月或者3个月更新一下排序,统计上1或者3个月的成交、点击、转换情况,微调整参数。
及时发现照顾不周的或者消弱作弊的或者新的导向等等。这部分排序更新也应当公开一些,让所有利益相关者心里明白这些变动。
长期不更新,一帮第三产业,针对搜索优化的人就有收入了。并且他们非常高明的。

    

动态排序

带推荐因素的动态排序,可以理解就是个性化排序。就是将用户登录信息(ip地域、登录时间)、用户身份信息(性别、年龄)、
用户行为信息(购买、点击、评价、互动等)参数抽取加入查询条件中,或者影响排序因子。

    

排序实例讲解

主要针对默认排序,facet、group、highlight使用做通俗讲解,对于按指定域排序、区间查询等不讲,请参考 查询样例 查询语法
举例字段默认名称为title、count。
特别注意:下面的举例务必结合应用具体情况,具体测试看效果。
不可死搬照套去做,描述基本上是“文字性的”。

    

场景1 多个词联合查询

 例如: 输入 "淘宝 杭州",对返回结果有N种理解
  (1)包含"淘宝"的或者包含"杭州"的都行
  (2)包含"淘宝"或者包含"杭州",同时包含"淘宝"和"杭州"的排在前面
  (3)同时包含"淘宝"和"杭州"
  (4)包含"淘宝"的比包含"杭州"的靠前
针对(1) String queryStr=“title:(淘宝 杭州)” 或者 String queryStr=“title:淘宝 OR title:杭州”
表示查询title域中包含淘宝或者包含杭州的文档。注意:不保证同时包含“淘宝”与“杭州”的就一定排在最前面,
可能排在前10条,但不一定前5条或者前1条。

针对(2) String queryStr="title:("淘宝 杭州"~10)"; 表示搜索淘宝 与杭州的文档,这两个词之间其他词个数为
10byte(对应英文10个字母,包括空格标点等内容)。或者 String queryStr ="title:("+""淘宝 杭州"~10";
或者 String queryStr="title:淘宝杭州 OR title:(淘宝 杭州)",这个也不保证淘宝杭州的结果一定靠前。进一步
String queryStr="title:淘宝杭州^5 OR title:(淘宝 杭州)",就可以保证淘宝杭州按着的得分相对高些,
通常能达到预期效果
这样出来的结果相对有好转,但不保证一定所有词都符合期望,还与文档集合有关。同时,参数^5 看具体应用,是可以自行设置的。
针对(3) String queryStr="title:淘宝 AND title:杭州",这样一定出来的结果中包含淘宝并且包含杭州,
然后包含这些词的文档顺序如果不满意,需要引入position信息了,不细讲。有需求在说。
针对(4) String queryStr="titile:(淘宝^5 杭州)"
所有处理,只保证相对性,不保证绝对性,因为与文件集合本身有关联。这里的参数^5 其中5是可以自行设置的。

    

场景2 统计查询结果

 统计就是facet功能。根据query条件查询的结果,按照设置的facet域,对设置的一个或者多个域的内容,
在当前查询条件命中的结果集中遍历并统计。所以,如果命中结果非常多,或者要统计的域的字条数目非常大,
系统性能有一定的影响。上线应用中,如果facet查询比例很大,需要考虑性能压测和优化。
TerminatorQueryRequest query = new TerminatorQueryRequest();
String queryString="title:淘宝"
query.setFacet(true);//开启facet统计功能
query.addFacetField("count");
query.setRows(10);//设置返回结果条数,如果你时分组查询,你就设置为10
query.addFacetField("app_id");//增加分组字段
 上面的查询,表示查询title这个域中包含"淘宝"的结果,并对这一次结果统计两个域值,一个count这个域不同域值出现的次数
一个app_id出现次数。
 例如假设命中5篇文档,大概内容如下
doc1   title=淘宝 count={abc,abd, bc, dd} app_id={11,13,14}
doc2  title=淘宝 count={abcd,abd, ac, dd} app_id={11,13,15}
doc3  title=淘宝 count={abc,abd, dc, dd} app_id={11,16,14}
doc4  title=淘宝 count={abc,abd, dc, dd} app_id={11,13,15}
doc5  title=淘宝 count={bcd,abd, dc, dd} app_id={11,18,14}
那么统计结果是:
count这个域
    abc=3,abd=5,bc=1,dd=5,abcd=1,ac=1,bcd=1
app_id这个域
    11=5,13=4,14=3,15=1,16=1,18=1
具体数据结构可以从查询返回对象中获取。

    

场景3 结果分组

 分组就是根据查询条件,对获得的结果集文档按照某个域值进行分组。3.0以后版本支持!
TerminatorQueryRequest query = new TerminatorQueryRequest();
String queryString="title:淘宝"
query.setParam("group","true");
query.setParam("group.field","count");
表示对包含淘宝的文档集合,然后按照count域值进行分组。假设命中下面5篇文档,
doc1   title=淘宝 count={abc,abd, bc, dd} app_id={11,13,14}
doc2  title=淘宝 count={abcd,abd, ac, dd} app_id={11,13,15}
doc3  title=淘宝 count={abc,abd, dc, dd} app_id={11,16,14}
doc4  title=淘宝 count={abc,abd, dc, dd} app_id={11,13,15}
doc5  title=淘宝 count={bcd,abd, dc, dd} app_id={11,18,14}
group的结果就是
 group1 abc=3 {doc1 doc3 doc4}
 group2 abd=5 {doc1 doc2 doc3 doc4 doc5}
 group3 bc=1  {doc1}
 group4 dd=5  {doc1 doc2 doc3 doc4 doc5}
 group5 abcd=1 {doc2}
 group6 ac=1 {doc2}
 group7 bcd=1 {doc5}
更多关于group的参数,具体应用中在core下就ok了。

    

场景3 结果集高亮

TerminatorQueryRequest query = new TerminatorQueryRequest();
String queryString="title:淘宝"
query.setHighlight(true); // 启动highlight
query.addHighlightField("title"); //highlight 域,注意这个域需要设置为stored=true
query.setHighlightRequireFieldMatch(false);//是否匹配
query.setHighlightSimplePre("");//高亮表示符号
query.setHighlightSimplePost("");
表示查询title域中包含淘宝的文件集,并对命中文本高亮。
对应有些字段,不是匹配性高亮,例如价格,那么可以直接在页面展示时,固定高亮就ok了。这样可以提升系统性能。
还可以直接将高亮信息存储到索引中,查询返回自带高亮内容。此时的高亮域查询无关的。

    

场景4 多域排序

    (1)独立多个域(注意作弊控制)

例如: sortby_A desc sortby_B asc sortby_C asc 等。表示当第一维度值相同,按第二维度排序,第二维度
也相同,按第三维度排序。依次类推。如果达到第四维度排序,数据已经非常“密集”了,或者说数据之间的细微差别
不是很明显了。真有这么好的数据,我是说如果,那这个产品的长尾、个性就非常nb了。但实际上,很少有这么好的数据。
通常在第二、第三维度就将数据分开了。
多域排序是否可以合并一个域?
默认情况下是不可以的。因为,合并的域就是文本类型,文本类型比较就是ascii吗了。数值比较可能丢失信息了。
可以自定义数据结构将多个域 并接为byte类型,或者“逻辑组合运算”为一个域值。这对开发要求高。
在简单可行的基础上,直接多个域吧。

    (2)拼接域

例如固定的几个域排序,将各个子域按固定位数拼接。例如int 分4段,每段8位。好处,按序比较。

    (3)综合模型

多个域按权重、按得分模型计算得分。

    

其他

排序是搜索质量的核心之一,难点很多,不同场景不同需求。更复杂的问题或者场景请您反馈、交流。
24小时在线响应,欢迎随时骚扰***同学!

建议继续学习

  1. 如何使用1M的内存排序100万个8位数 (阅读 12,222)
  2. 快速排序(Quicksort)的Javascript实现 (阅读 11,543)
  3. 腾讯-1亿个数据取前1万大的整数-题解答 (阅读 9,944)
  4. 深入浅出插入类排序算法(直接插入, 折半插入, 希尔排序) (阅读 7,424)
  5. 深入浅出交换类排序算法(冒泡排序,快速排序) (阅读 6,983)
  6. Java程序员必知的8大排序算法 (阅读 5,561)
  7. Mysql中的排序优化 (阅读 5,521)
  8. Vim(gVim)对排序的妙用 (阅读 5,281)
  9. 快速排序详细分析 (阅读 4,921)
  10. 深入浅出选择类排序算法(简单选择排序,堆排序) (阅读 4,543)