阅读642 返回首页    go 汽车大全


相关性实战__功能篇_最佳实践_开放搜索-阿里云

针对目前若干用户遇到的搜索结果与预期不符合的问题进行统一详细说明,并以此为话题展开说明下opensearch在搜索效果方面的功能和后续一些工作方向。

首先,对于搜索来讲,最常见的有两种做法:

  1. 数据库的like查询,可以理解为简单的包含关系;
  2. 百度、google等搜索引擎,涉及到分词,将查询词根据语义切分成若干词组term(这个是搜索引擎重难点之一),通过term组合匹配给相应文档进行打分,根据分值排序,并最终返回给用户。

opensearch采用的方式与上述搜索引擎做法基本一致。那这里就有三部分内容会影响搜索效果:1,分词方式;2,匹配方式;3,相关性算分。

我们来分别说下这三部分在opensearch上的行为和表现。

分词方式

原理

分词会在两个地方使用:

  1. 索引构建时:接收到用户推送文档后,会根据用户定义的应用结构,取出其中为TEXT、SWS_TEXT字段进行分词,将对应文档内容分成若干term(如"浙江大学"拆分成2个term:"浙江"和"大学"),并针对每个索引字段配置(可搜索的索引字段)构建term到文档doc的倒排链表,用于快速召回使用;
  2. 查询时:将查询词进行分词,按照切完后的term查找倒排链,从而找到(召回)包含该term的文档。 由此可见,这两部分的分词方式必须一致,否则会出现对应文档无法召回的情况。

接下来,我们详细说明下各个字段的展现效果及适用场景,供大家参考。

STRING

不分词,适合一些需要精确匹配或者只展示不搜索的场景,如标签、关键词、url等。

如文档字段内容为“菊花茶”,则只有搜索“菊花茶”的情况下可以召回。

TEXT、MWS_TEXT

按照检索单元做分词,适合有语义的中文搜索场景,如标题、文本等,MWS_TEXT是TEXT的扩展,会召回更多的内容,建议使用MWS_TEXT。

如文档字段内容为“菊花茶”,则搜索“菊花茶”、“菊花”、“茶”、“花茶”的情况下可以召回。

SWS_TEXT

按照单字/单词分词,适合非语义的中文搜索场景,如小说作者名称、店铺名等;

如文档字段内容为“菊花茶”,则搜索“菊花茶”、“菊花”、“茶”、“花茶”、“菊”、“花”、“菊茶”的情况下可以召回。

SHORT_TEXT

短文本模糊搜索,支持拼音搜索、数字的前后缀搜索、单字或者单字母搜索。最多支持100个字节字段长度,更多介绍及注意事项参见模糊搜索使用说明

如文档字段内容为“菊花茶”,则搜索“菊花茶”、“菊花”、“茶”、“花茶”、“菊”、“花”、“菊茶”、“ju”、“juhua”、“juhuacha”、“j”、“jh”、“jhc”等情况下可以召回。
如文档字段内容为手机号“13812345678”,则通过“^138”来搜索以“138”开头的手机号,通过“5678$”搜索以“5678”结尾的手机号;
如文档字段内容为“OpenSearch”,则通过单个字母或者组合都可以检索到。

ENG_TEXT

英文分词,适合于英文搜索场景,对于分词后的每个英文单词默认会做去词根、单复数转化。

如文档字段内容为“英文分词器 english analyzer”,则搜索“英文分词器”、“english”、“analyz”、“analyzer”、“analyzers”、“analyze”、“analyzed”、“analyzing”。
(注意:英文分词器中连续的中文会被分成一个词)

NWS_TEXT

自定义分词,适合特殊场景下系统自带无法解决的搜索场景,可以实现完全用户控制的效果。推送文档及搜索时使用制表符“t”对字段内容(或查询词)进行分隔,注意二者分词的一致性,否则会导致无法召回文档的情况。

如字段内容为“菊t花茶thao”,则只有查询词“菊”、“花茶”、“菊t花茶”、“花茶thao”、“菊thao”、“菊t花茶thao”可以召回该文档。

后续工作

  1. 增加对小语种的支持,如俄语、葡语、日语等。

使用技巧

1,在一些召回不好的情况下,可以采用TEXT和SWS_TEXT字段结合的方式来保证搜索效果的同时提高召回率。具体做法为定义两个相同内容的字段分别为title(TEXT)及sws_title(SWS_TEXT),并分别建立索引字段为title_search、sws_title_search。则查询词为query=title_search:'keyword' OR sws_title_search:'keyword',并设置精排表达式为text_relevance(title)*10+field_proximity(sws_title),在保证相关性的同时保证召回。

匹配方式

原理

分完词后得到若干term,如何召回文档,就涉及到匹配方式。目前opensearch内部默认支持的是AND,即一篇文档中包含全部的term才能被搜索出来。当然这是对同一关键词而言的,除此之外系统还支持多种匹配方式,如AND、OR、RANK、NOTAND以及(),优先级从高到低为(),ANDNOT,AND,OR,RANK。

举例

关系 用法 含义
query=title:”苹果 手机” 查询title中包含苹果和手机的文档
AND query=title:’苹果’ AND cate:’手机’ 交集。查询title中包含苹果,且cate包含手机的文档
OR query=title:’苹果’ OR cate:’手机’ 并集。查询title中包含苹果,或cate包含手机的文档
RANK query=title:’苹果’ RANK cate:’手机’ 查询title中包含苹果的文档,如果cate包含手机则可以加分
ANDNOT query=title:’苹果’ ANDNOT cate:’手机’ 查询title中包含苹果,但cate不包含手机的文档

案例

  1. 问:我文档中包含“吃饭了”,我搜索“吃饭”、“吃饭了”都能召回,搜索“吃饭了吗”没结果? 答:因为目前opensearch是要求全部的分词结果都匹配才能召回文档,上面的“吗”在文档中没有出现,所以无法召回。
  2. 问:我只想查找某些词排在最前面的文档,比如以“肯德基”开头的文档; 答:目前不支持位置相关召回。

后续工作

  1. 我们正在开发query分析的功能,会对不重要的词做rank,如案例1中的”吃饭了吗”会改写成”吃饭” AND ”了” RANK ”吗”,召回“吃饭了”的文档,并将“吃饭了吗”的文档排在前面。
  2. 支持用户词典,比如纠错、同义词等,可以根据自己的实际场景挖掘出属于自己的专属词典。
  3. O2O实体词识别,如query=title:’杭州市文一西路’改写为query=title:’杭州市文一西路’ OR (city:’310010’AND district:’0012’ AND title:’文一西路’)。
  4. 支持下拉提示、相关搜索功能。
  5. 热词统计、点击反馈等。

使用技巧

  1. 可以通过AND,OR等实现强大的搜索功能。
  2. 对于一些filter中的过滤字段,如= 、!=的需求,可以尽量使用索引字段来做,可以提高查询性能。点击获取更多优化小技巧

相关性算分

上面提到的都是跟召回相关的技术,召回文档之后,究竟文档如何排序就涉及到相关性。 目前opensearch有sort子句来支持用户自定义排序。如果不设置sort,则默认为sort=-RANK;sort本身支持多维排序,以及升降序的支持。比如sort=-RANK;+bonus,意思为第一位按照相关性降序排序,相关性分值一样的文档再按照bonus升序排列。 这里我们重点描述下RANK的用法,RANK即为opensearch中的相关性设置,主要分为两部分:粗排和精排,分别有对应的控制台中的粗精排表达式配置

原理

Opensearch相关性算分策略为,取召回的rank_size(目前是100万)个文档按照粗排表达式的定义进行算分;取粗排分最高的N个结果(百级别)按照精排表达式进行算分,并排序;然后根据start与hit的设置取相应结果返回给用户。如果用户获取的结果超过了精排结果数N,则后续按照粗排分数排序结果继续展现。

  1. 粗排表达式:从上面原理介绍中可以看出粗排对性能(latency)的影响非常大,但同时粗排又非常的重要,否则会出现好的文档无法进入精排而导致文档不能被最终展现。所以粗排要尽量的简单有效,目前opensearch的粗排只支持几个简单的正排字段、静态bm25、时效分等因素。
  2. 精排表达式:通过粗排表达式筛选出较优质的N个文档进行详细排序,精排表达式中支持复杂的数学计算、逻辑等,并且opensearch提供了丰富的典型场景(如O2O类)的function和feature来满足日常的相关性需求。

同时,系统以内置了多个场景的应用结构和排序表达式,可以供大家参考和使用。

举例

场景 表达式 含义
论坛-排 static_bm25() 简略文本分
论坛-精排 text_relevance(title)*3+text_relevance(body)
+if(text_relevance(title)>0.07,timeliness(create_timestamp),timeliness(create_timestamp)*0.5)
+(topped+special+atan(hits)*0.5+atan(replies))*0.1
文本分
时效分
其他属性分
O2O-粗排 sold_score+general_score*2 销量、门店综合分值(离线算好)
O2O-精排 2*sold_score+0.5*reward
- 10*distance(lon,lat,u_posx,u_posy)
+ if ((flags&2) ==2, 2, 0)+if(is_open==5,10,0)
+ special_score
销量、配送速度及准点率
距离
是否繁忙、是否在营业时间
人工干预
小说-粗排 static_bm25()*0.7+hh_hot*0.00003 文本分、热度
小说-精排 pow(min(0.5,max(text_relevance(category),max(text_relevance(title), text_relevance(author)))),2)
+ general_score*2
+ 1.5*(1/(1+pow(2.718281,-((log10(hh_hot)-2)*2-5)))))
分类相关性、标题相关性、作者相关性
小说质量
小说热度
电商-粗排 static_bm25()+general_score*2+timeliness(end_time) 文本分、宝贝综合分值、过期时间
电商-精排 text_relevance(title)*3+text_relevance(category)
+ general_score*2+boughtScore*2
+ tag_match(ctr_query_value,doc_value,mul,sum,false,true)+..
文本相关性、类目相关性
宝贝人气、卖家分
ctr预估、特征规则分等

案例

  1. 问:精排表达式text_relevance(seller_id)报找不到字段 答:text_relevance()只支持TEXT及SWS_TEXT类型,其他不可以。

  2. 问:查询报2112错误,是什么问题? 答:查询语句(query子句)必须与formula相配合,比如query=default:'keyword',default中包含title和body字段,而formula指定text_relevance(title)+text_relevance(author)则会报错,因为author在default中不存在。

后续工作

  1. 优化错误码,目前很多查询错误都会报1000错误,不利于用户定位问题,且容易造成系统有问题的误导,后续会统一进行梳理。
  2. 后续会对电商类场景提供更多样的feature来支持,如有类似的需要请联系我们。
  3. 发布截断功能,允许用户指定重要字段,构建索引时考虑该字段的值,降低参与粗排文档数、提高参与精排文档数,即降低查询开销又提高搜索质量,让更多好的文档能够排上来。
  4. 相关性ABTest调试界面,会在搜索测试页面增加多个排序表达式的对比界面,将每项表达式的值列出来,方便用户进行排序表达式的调整。

使用技巧

  1. 排序表达式的算分是在查询结算对每个文档进行计算的,所以如果跟查询无关的部分的计算可以预先离线计算好,新增一个general_score字段来存放,排序的时候只要使用general_score字段即可,避免大量计算过程,提高查询性能。
  2. tag_match的feature允许用户将query中的特征与doc中特征做多维运算,在电商场景下有着非常广泛的用途,有类似的需求的用户可以研究下。
  3. opensearch提供了丰富的function和feature,使用得当可以获得非常强大的功能。
  4. 相关性有很多部分共同组成,各项之间的权重需要根据搜索排序效果不断进行调整以达到一个用户满意的搜索效果。

最后更新:2016-11-23 17:16:06

  上一篇:go 相关下载__JavaSDK手册_SDK参考手册_开放搜索-阿里云
  下一篇:go Array数组类型说明__功能篇_最佳实践_开放搜索-阿里云