【ElasticSearch】搜索结果处理:排序、分页、高亮

迷南。 2023-10-13 12:58 108阅读 0赞

文章目录

  • 1、排序
  • 2、分页
  • 3、高亮

1、排序

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

  1. # 数值、keyword、日期等类型排序的语法
  2. GET /indexName/_search
  3. {
  4. "query": {
  5. "match_all": {
  6. }
  7. },
  8. "sort": [
  9. {
  10. "FIELD": "desc" // 排序字段和排序方式ASC、DESC
  11. }
  12. ]
  13. }

地理类型坐标排序的语法:

  1. GET /indexName/_search
  2. {
  3. "query": {
  4. "match_all": {
  5. }
  6. },
  7. "sort": [
  8. {
  9. "_geo_distance" : {
  10. "FIELD" : "纬度,经度", //经纬度位置字段FIELD,你的位置"纬度、经度"
  11. "order" : "asc",
  12. "unit" : "km" //最后显示为哪个单位,距离你5KM
  13. }
  14. }
  15. ]
  16. }

案例一:对酒店数据按照用户评价降序排序,评价相同的按照价格升序排序

在这里插入图片描述

  1. GET /hotel/_search
  2. {
  3. "query": {
  4. "match_all": {
  5. }
  6. },
  7. "sort": [
  8. {
  9. "score": "desc"
  10. },
  11. {
  12. "price": "asc"
  13. }
  14. ]
  15. }

在这里插入图片描述
案例二:实现对酒店数据按照到你的位置坐标的距离升序排序

  1. 获取经纬度的方式:
  2. https://lbs.amap.com/demo/jsapi-v2/example/map/click-to-get-lnglat/

这个案例在实际场景中即是:

在这里插入图片描述

  1. GET /hotel/_search
  2. {
  3. "query": {
  4. "match_all": {
  5. }
  6. },
  7. "sort": [
  8. {
  9. "_geo_distance" : {
  10. "location" : "31.0,121.6",
  11. "order" : "asc",
  12. "unit" : "km"
  13. }
  14. }
  15. ]
  16. }

在这里插入图片描述

以上两个案例中,指定排序字段后,可以看到返回结果中_score为null,即指定排序字段,ES就不用打分了,这样对查询性能也有一定提升。

2、分页

ES底层有默认的分页参数,因此默认情况下只返回top10的数据,可通过修改from、size参数来控制要返回的分页结果:

  1. {
  2. "query": {
  3. "match_all": {
  4. }
  5. },
  6. "from": 990, // 分页开始的位置,默认为0
  7. "size": 10, // 期望获取的文档总数
  8. "sort": [
  9. {
  10. "price": "asc"}
  11. ]
  12. }
  13. //有点像MySQL的LIMIT,第一个参数从哪儿开始,第二参数为行数

举例:

在这里插入图片描述

比如from值为990,size为10,不同于MySQL的正排索引,ES的倒排索引只能先查出前1000条,再截取990-1000条的文档:

在这里插入图片描述

这一点在分布式的ES集群中,就产生了深度分页问题。

  1. 例如按price排序后,获取from = 990size =10的数据:
  • 首先在每个数据分片上都排序并查询前1000条文档
  • 然后将所有节点的结果聚合在内存中重新排序选出前1000条文档
  • 最后从这1000条中,选取从990开始的10条文档

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

在这里插入图片描述

如果真有这个超10000的需求,ES官方提供两种解决方案:

  1. search after

分页时需要排序,原理是从上一次的排序值开始,查询下一页数据。官方推荐使用的方式

  1. scroll

原理将排序数据形成快照,保存在内存。官方已经不推荐使用

小结:

在这里插入图片描述

3、高亮

即在搜索结果中把搜索关键字突出显示,实现原理是:

  • 将搜索结果中的关键字用标签标记出来
  • 在页面中给这个标签添加css样式,如color:red

    GET /hotel/_search
    {

    “query”: {

    1. "match": {
    2. "FIELD": "TEXT" //这自然不能用match_all了,不然关键字都没了,何谈高亮
    3. }

    },
    “highlight”: {

    1. "fields": {
    2. // 指定要高亮的字段
    3. "FIELD": {
    4. "pre_tags": "<em>", // 用来标记高亮字段的前置标签
    5. "post_tags": "</em>" // 用来标记高亮字段的后置标签
    6. }
    7. }

    }
    }

F12看下:

在这里插入图片描述

举例:

在这里插入图片描述
改require_field_match为false:

在这里插入图片描述
到此,搜索基本结束,综合起来如下:

  1. GET /hotel/_search
  2. {
  3. "query": {
  4. "match": {
  5. "name": "如家"
  6. }
  7. },
  8. "from": 0, // 分页开始的位置
  9. "size": 20, // 期望获取的文档总数
  10. "sort": [
  11. {
  12. "price": "asc" }, // 普通排序
  13. {
  14. "_geo_distance" : {
  15. // 距离排序
  16. "location" : "31.040699,121.618075",
  17. "order" : "asc",
  18. "unit" : "km"
  19. }
  20. }
  21. ],
  22. "highlight": {
  23. "fields": {
  24. // 高亮字段
  25. "name": {
  26. "pre_tags": "<em>", // 用来标记高亮字段的前置标签
  27. "post_tags": "</em>" // 用来标记高亮字段的后置标签
  28. }
  29. }
  30. }
  31. }

发表评论

表情:
评论列表 (有 0 条评论,108人围观)

还没有评论,来说两句吧...

相关阅读