《Elastic Stack 实战手册》——四、应用实践——4.1 企业搜索应用场景 ——4.1.2.实现主流搜索引擎广告置顶显示效果(上) https://developer.aliyun.com/article/1226383
Pinned query 实战实现
基础数据 Demo 如下,直接拿文章开头的截图示例模拟一下,假设 id为 1、2、3 的3条数据是需要特意置顶显示的数据
PUT index_001 { "mappings": { "properties": { "title":{ "type": "text", "analyzer": "ik_max_word", "fields": { "keyword":{ "type":"keyword" } } } } } } PUT index_001/_bulk {"index":{"_id":1}} {"title":"大众汽车首款纯电动ID.4_预售进行时_先订先享"} {"index":{"_id":2}} {"title":"保时捷首款纯电动跑车Taycan - 现已到店 - 电驰神往"} {"index":{"_id":3}} {"title":"纯电动电动汽车?英国国际贸易部_邀您来投资英国汽车工业"} {"index":{"_id":4}} {"title":"四轮电动车_ 电动汽车报价_阿里巴巴采购批发_超多品类低价批发"} {"index":{"_id":5}} {"title":"电动汽车之家,为新能源汽车而生 - 第一电动网"} {"index":{"_id":6}} {"title":"中国电动汽车网_新能源汽车_电动汽车网"} {"index":{"_id":7}} {"title":"电车之家_领先的电动汽车及新能源汽车行业门户网站"}
如果要召回既包含:“电动汽车” 完全匹配,又包含“电动”或“汽车” 分词匹配的全量数据。大致的检索语句如下:
POST index_001/_search { "query": { "bool": { "should": [ { "match_phrase": { "title": { "query": "电动汽车", "boost": 5 } } }, { "bool": { "should": [ { "match": { "title": "电动" } }, { "match_phrase": { "title": "汽车" } } ], "minimum_should_match": 2 } } ] } } }
如上检索部分:完全匹配加了 boost 提升权重。
返回结果如下:
返回结果按照评分由高到低顺序排列,_id 序列为:5、7、3、6、4 ......
置顶显示_id 为 1、2、3 的数据,pinned query 实现如下:
GET index_001/_search { "query": { "pinned": { "ids": [ "1", "2", "3" ], "organic": { "bool": { "should": [ { "match_phrase": { "title": { "query": "电动汽车", "boost": 5 } } }, { "bool": { "should": [ { "match": { "title": "电动" } }, { "match_phrase": { "title": "汽车" } } ], "minimum_should_match": 2 } } ] } } } } }
本质是在原来检索语句的基础上,添加了如下部分代码:
"pinned": { "ids": [ "1", "2", "3" ], "organic": {
第一:置顶显示的 id ,写法如下:
第二:除了置顶数据之外的其余正常检索语句块内容。只是加了“organic” 包裹一层。其中的检索语句还是原来的写法 ,拷贝过来即可。
返回结果如下:
返回结果已 pinned(类似做了“广告位”定制),_id 序列为:1、2、3、5 ....... 实现了类百度置顶显示广告的效果。
Pinned query 源码解读
认知前提:源码中最大评分计算方法
float MAX_ORGANIC_SCORE = Float.intBitsToFloat((0xfe << 23)) - 1;
本质上与下面代码等价:
float max_rst = (float)Math.pow(2,127);//1.7014118E38
也就是说:MAX_ORGANIC_SCORE 大小为:2 的 127 次幂,是 Elasticsearch float 最大值。
最大评分作用
正常查询的评分得分不会超过 MAX_ORGANIC_SCORE, 将固定查询(pinned query)的评分设定为:MAX_ORGANIC_SCORE。
pinned query 保证置顶显示解密
原理:将置顶显示的数据通过 bool 组合查询 + boost 提升权重的方式给设置了 float 最大值评分,这样就能保证置顶显示了。
核心源码实现如下:
注意细节没有深究,比如:置顶返回的结果显示的是原始评分。
小结
读者可能会问:这并没有实现基于特定关键词返回特定数据的需求?其实有了pinned query 再将特定关键词与待置顶显示文章 _id ,建立个一对多的映射关系就可以实现。映射关系可以自己内存维护或者借助 redis 实现都可以。
你我发现的新需求,很可能别人早就发现,且已经提交 Git了。更可怕的是:官方新版本已经实现了!
要注重基础夯实的同时,多关注一下技术动态。两手抓、两手都要硬!
参考
l https://www.elastic.co/guide/en/elasticsearch/reference/7.4/release-notes-7.4.0.html
创作人简介:
铭毅天下,Elastic 认证工程师、Elastic 官方合作培训讲师、阿里云 MVP、CSDN 博客专家、铭毅天下 Elasticsearch 公众号作者、死磕 Elasticsearch 知识星球星主。近 10年工作经验,关注 Elastic Stack 技术栈、大数据技术领域。