1、需求

  • wx私信问题:Elasticsearch 如何实现类似百度广告置顶显示给定商品数据的效果?

置顶显示某特定数据就是:搜索某关键词,出现关联广告置顶显示的效果。

举例:百度搜索“电动汽车”,结果如下:

上面实现的本质:返回结果的第一页头1条或多条数据是服务端(如电商网站、主流搜索引擎)指定的数据,而非按照相关度评分计算得出的结果数据。

这时候,不禁要问 Elasticsearch 能实现类似功能不 ?

2、拆解实现

Elasticsearch from + size 分页实现机制的原理(大致意思):

  • page 1:from 0,size:10——返回第 0 到 第 9 条数据。

  • page 2:from 10,size:10——返回第 0 到 第 19 条数据,截取第 10 到 第 19 条数据;

  • page 3:from 20,size:10——返回第 0 到 第 29 条数据,截取 第 20到 第 29 条数据。

  • ......

本质是深度分页,肯定越往后翻页响应越慢。

要实现根据固定关键词添加特定数据置顶显示的效果,探讨方案如下:

2.1 方案一:不重新分页,牺牲首页部分数据

不再做重新分页,强制将 page 1 部分数据,换成:类【广告位】置顶显示数据。

显然,会有数据丢失,导致搜索精准率下降,用户一般不会接受。

2.2 方案二:重新内存分页

将类【广告位】置顶显示数据 + 已有返回的前10页(举例:100 条数据)重新组合后,再分页。

需要内存维护一堆数据,有较大内存开销。用户期望翻页越深(比如:100页+),维护数据越大,处理越慢、延时会越明显。

2.3 方案三:其他方案

类主流搜索引擎实现的方法或者读者新的实现机制。

但,此时要想,有没有更简洁的实现呢?

Elastic 官方就没有考虑这个用户需求吗?

有的,Elasticsearch 7.4.0 新增的 pinned query 就能实现这种功能。

且听慢慢道来......

3、pinned query 介绍

pinned query 是 Elasticsearch 7.4.0 版本实现的增强检索功能。

pinned:中文翻译为“固定”。

pinned query 则可以解释为——固定某些结果首页置顶显示的检索方式。

下图更能形象的说明:绿色的 Pinned results 就是要首页置顶显示的结果。

4、 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 ,写法如下:

  "pinned": {"ids": [

第二:除了置顶数据之外的其余正常检索语句块内容。只是加了“organic” 包裹一层。其中的检索语句还是原来的写法 ,拷贝过来即可。

返回结果如下:

返回结果已 pinned(类似做了“广告位”定制),_id 序列为:1、2、3、5 ....... 实现了类百度置顶显示广告的效果。

5、 pinned query 源码解读

5.1 认知前提:源码中最大评分计算方法

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 最大值。

5.2 最大评分作用

正常查询的评分得分不会超过 MAX_ORGANIC_SCORE, 将固定查询(pinned query)的评分设定为:MAX_ORGANIC_SCORE。

5.3  pinned query 保证置顶显示解密

原理:将置顶显示的数据通过 bool 组合查询 + boost 提升权重的方式给设置了 float 最大值评分,这样就能保证置顶显示了。

核心源码实现如下:

注意细节没有深究,比如:置顶返回的结果显示的是原始评分。

6、小结

读者可能会问:这并没有实现基于特定关键词返回特定数据的需求?其实有了pinned query 再将特定关键词与待置顶显示文章 _id 建立个一对多的映射关系就可以实现。映射关系可以自己内存维护或者借助 redis 实现都可以。

你、我发现的新需求,很可能别人早就发现,且已经提交 Git了。更可怕的是:官方新版本已经实现了!

要注重基础夯实的同时,多关注一下技术动态。两手抓、两手都要硬!

参考:

  • https://www.elastic.co/guide/en/elasticsearch/reference/7.4/release-notes-7.4.0.html

推荐:

  1. 全网首发!《 Elasticsearch 最少必要知识教程 V1.0 》低调发布

  2. 从实战中来,到实战中去——Elasticsearch 技能更快提升方法论

  3. 你的 Elasticsearch 难题,官方文档早就有了答案......

  4. 从提高 Elasticsearch 搜索体验说开去......


中国最大的 Elastic 非官方公众号

点击查看“阅读原文”,获取近10小时进阶视频教程,和全球近 1000 位 Elastic 爱好者一起每日精进 ELK 技能!

Elasticsearch 如何实现类主流搜索引擎广告置顶显示效果?相关推荐

  1. 微服务框架 SpringCloud微服务架构 25 黑马旅游案例 25.4 广告置顶

    微服务框架 [SpringCloud+RabbitMQ+Docker+Redis+搜索+分布式,系统详解springcloud微服务技术栈课程|黑马程序员Java微服务] SpringCloud微服务 ...

  2. Lucene,Elasticsearch,Solr,Xapian,Sphinx主流搜索引擎的对比

    Lucene 系别:JAVA 基于Java的一个开放源代码的全文检索引擎工具包,注意是工具包,所以严格来说它并不是一个搜索引擎服务程序,开发者需要了解搜索引擎的基本原理和Lucene的用法,然后根据需 ...

  3. hexo博客文章置顶功能实现的两种方法

    写在前面 本文主要描述了如何实现hexo文章置顶功能,讲述了通过修改源码和通过更改插件两种方式实现,以及如何添加置顶显示.文章可能还有很多不足,请大家谅解,欢迎大佬提意见. 本文使用的东西 win10 ...

  4. 从一个置顶CPT广告学习计算广告设计要点

    Outlook > Knowledge > IQ 达芬奇有很高的 IQ,在他的时代构想了很多发明,却不能够实现自己的发明 亨利·福特出生在合适的年代,在福特的时代,他拥有足够知识,得以制造 ...

  5. Java集成ElasticSearch及配置类工具类整理

    Java集成ElasticSearch及配置类工具类整理 前言:做一个有梦想的程序猿! ES不同的版本API差异比较大,此处ES版本为:6.5.3 代码如下: 添加Maven依赖 <!-- ES ...

  6. 国外主流搜索引擎提交入口

    为什么要向搜索引擎提交网站?因为当你的网站成完建设好后并将内容填充上,这时就需要对外向搜索引擎提交的你网站,加速让你的网站在搜索引擎中展示,因为SEO的第一步就是让网站被搜索引擎收录,今天收集了国外主 ...

  7. 百度搜索引擎广告SEM调用架构示意图

    下面是从百度计算广告学教程的一份ppt中摘取的几张图片,它们清晰地给出了搜索引擎广告的投放流程,以便参考. 参考文献 [1].百度搜索广告系统工程架构.ppt

  8. 初识 ElasticSearch,一个上天下地的搜索引擎 No.158

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试资料 我想跟大家先讲这么一个故事.在2017年,我有幸参与到Elasti ...

  9. 全国计算机棋类竞赛,自主招生认可的12类主流竞赛详解

    自主招生认可的12类主流竞赛详解 2016年全国有90所自主招生院校,其中77所针对全国招生,13所针对本省招生.在如此多的自主招生院校中,大家最为感兴趣的就是,2017高校自主招生到底认可什么样的竞 ...

  10. 搜索引擎广告计费系统如何防恶意点击

    你在一些搜索引擎上搜索"传智播客"和"java培训",就会看到一些广告链接,只要你随手点击一下这些广告链接,就会消耗广告发布商的费用,广告发布商必须为这次点击付 ...

最新文章

  1. 递增三元组蓝桥杯c语言,第九届蓝桥杯_递增三元组(枚举的优化思路)
  2. 通过 运行实现快速打开应用程序
  3. php面向对象mysqli,php+mysqli使用面向对象方式更新数据库实例
  4. cornerMinEigenVal函数
  5. 爬虫 404 try_无所不能的Python之爬虫那点事儿
  6. html下拉框变长,改变HTML下拉框SELECT选项的多种方法
  7. 性能监控—spotlight监控mysql性能
  8. javascript setTimeout 和 setInterval 区别
  9. mysql 数据库 向上取整_PHP取整,四舍五入取整、向上取整、向下取整、小数截取...
  10. log4j控制日志的输出文件
  11. 初步认识泊松重建(比较全的综合教程)
  12. 计算机课平时成绩重要吗,大学计算机基础课程平时成绩评定方法的研究.pdf
  13. 阿里云推送ReactNative简单集成
  14. 百度地图API的IP定位城市和浏览器定位
  15. java就业感言_JAVA就业班感言
  16. int java 声明_怎样用java定义一个int数组 C++ 怎么声明一个整型数组?
  17. 一篇文章带你了解Nodejs
  18. php获取prepay_id时报错,微信支付获取prepay_id返回签名错误,官方demo中的签名方法MD5验证有问题...
  19. 下载模拟器提示关闭hyper,重启电脑不生效
  20. 59.【初识JFrame和数据库——聊天系统】

热门文章

  1. 你想要的宏基因组-微生物组知识全在这(2020.7)
  2. 【暴强】200种好口碑便宜护肤品 - 健康程序员,至尚生活!
  3. Centos自动登录
  4. 关于 mysql数据库“ERROR 1118 (42000): Row size too large.“ 的解决方法
  5. 消防工程师 10.3 火灾自动报警系统-可燃气体、电气火灾、消控室 11.灭火器
  6. Java语言十五讲(第十四讲 容器框架二)
  7. Flutter Package 开发、发布、使用
  8. The error occurred while setting parameters
  9. 正则表达式高级用法: 分组
  10. Debian 7修改SSH端口并设置防火墙端口放行