当前位置:首页 > 资讯 > 正文

ElasticSearch搜索结果处理

ElasticSearch搜索结果处理

elasticsearch支持对搜索结果排序,默认是根据相关度算分(_score)来排序。可以排序字段类型有:keyword类型、数值类型、地理坐标类型、日期类型等。

对结果的排序语法如下:

对酒店数据按照用户评价降序排序,评价相同的按照价格升序排序,评价是score字段,价格是price字段,按照顺序添加两个排序规则即可。

执行后结果如下:按照评分的高低排序,如果评分相同,在按照价格升序排序。

实现对酒店数据按照到你的位置坐标的距离升序排序,获取经纬度的方式: https://jingweidu.bmcx.com/,这里以虹桥机场的经纬度为坐标,

代码如下:

执行后结果如下:

ES中分页跟MySQL很像,但是它的底层原理,有很大的差别,ES底层采用倒排索引,它的结构是不利于做分页的,实际上采用的是逻辑上的分页,比如查990到1000的数据,对ES来讲它或查询0到1000的所有数据,然后去截取990-1000的部分

这种截取在单点查询的时候没有问题,但是ES为了存储更多的数据,ES做了集群。

elasticsearch默认情况下只返回top10的数据。而如果要查询更多数据就需要修改分页参数了。

elasticsearch中通过修改from、size参数来控制要返回的分页结果:

ES做了集群,ES把数据进行了拆分放到不同的机器上,拆分出来的每一分叫做一个分片,每一个分片上的数据是不一样的,要查询990-1000的数据,就不知道是哪一个分片的前1000条数据了

ES是分布式的,所以会面临深度分页问题。例如按price排序后,获取from=990,size=10的数据:

  1. 首先在每个数据分片上都排序并查询前1000条文档。
  2. 然后将所有节点的结果聚合,在内存中重新排序选出前1000条文档
  3. 最后从这1000条中,选取从990开始的10条文档

如果搜索页数过深,或者结果集(from+size)越大,对内存和CPU的消耗也越高。因此ES设定结果集查询的上限是10000

针对深度分页,ES提供了两种解决方案,宜方文档:

  • search after:分页时需要排序,原理是从上一次的排序值开始,查询下一页数据。官方推荐使用的方式。
  • scroll:原理将排序数据形成快照,保存在内存。官方已经不推荐使用。

注意:

  • search after:搜索是必须先排序,比如说按照价格排序,排序后就有了顺序,比如说先查询0-10条数据,第二次查询接下来10条的时候,会记录第十条排序的价格值,再次查询的时候可以从这个价格值往后去查询 有一个缺点,知道了上一次分页查询的最后一条数据值,往后查,不能够往前查询,数据只能往后分页,不能往前分页
  • scoll:查询方式是一个快照,第一次查询的时候,我把所有的数据都给你缓存起来,将来你要查询的时候,我再给你截取你需要的部分,这种方式对内存的消耗方式是非常大的不推荐使用 它形成了快照,当你更新了一条文档数据,你这条快照会更新吗,查询到的数据是旧的数据,没有办法查询到实时的数据

按照价格price字段,安装asc生效排序分页,显示第一页10条数据如下:

1)from+size:

  • 优点:支持随机翻页
  • 缺点:深度分页问题,默认查询上限(from+size)是10000
  • 场景:百度、京东、谷歌、淘宝这样的随机翻页搜索

2)after search:

  • 优点:没有查询上限(单次查询的size不超过10000)
  • 缺点:只能向后逐页查询,不支持随机翻页
  • 场景:没有随机翻页需求的搜索,例如手机向下滚动翻页

3)scroll:

  • 优点:没有查询上限(单次查询的size不超过10000)
  • 缺点:会有额外内存消耗,并且搜索结果是非实时的
  • 场景:海量数据的获取和迁移。从ES7.1开始不推荐,建议用after search方案。

高亮,就是在搜索结果中把搜索关键字突出显示。原理如下:

  • 将搜索结果中的关键字用标签标记出来
  • 在页面中给标签添加css样式

以百度搜索如下:

注意:

  • pre_tag、post_tags如果不写默认是添加em标签
  • ES搜索的字段必须与高亮的字段一致,如果不一致,需要添加require_field_match,默认是高亮字段和搜索字段不匹配 

根据我们创建all字段搜索,而高亮字段是name字段,这时候搜索的字段和高亮的字段不一致,所以需要设置参数"require_field_match"为 "false",默认就会给添加标签<em>,就没在写pre_tag、post_tags

执行后如下:

结合排序、分页和高亮对于结果进行处理,后续可以按照这个案例使用:

执行后结果如下:


最新文章