首页 > 其他分享 >ElasticSearch搜索结果处理

ElasticSearch搜索结果处理

时间:2023-11-29 11:34:28浏览次数:38  
标签:search 高亮 分页 处理 查询 搜索 ElasticSearch 排序 ES

一、排序

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

1.1.语法说明:

对结果的排序语法如下:

GET /indexname/_search
{
  "query": {
    "match_all": {}
  },
  "sort": [
    {
      "FIELD": {
        "FIELD": "desc" //排序字段和排序方式ASC、DESC
      }
    }
  ]
}

1.2.案例一:

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

GET /hotel/_search
{
  "query": {
    "match_all": {}
  },
  "sort": [
    {
      "score": "desc"
    },
    {
      "price": "asc"
    }
  ]
}

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

ElasticSearch搜索结果处理_数据

1.3.案例二:

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

ElasticSearch搜索结果处理_字段_02

代码如下:

GET /hotel/_search
{
  "query": {
    "match_all": {}
  },
  "sort": [
    {
      "_geo_distance": {
        "location": {
          "lat": 31.196955,
          "lon": 121.339752
        },
        "order": "asc",
        "unit": "km"
      }
    }
  ]
}

执行后结果如下:

ElasticSearch搜索结果处理_字段_03

二、分页

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

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

2.1.语法说明

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

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

GET /hotel/_search
{
  "query": {
    "match_all": {}
  },
  "from": 990, //分页开始的位置,默认为0
  "size": 10, // 期望获取的文档总数
  "sort": [
    {"price": "asc"}
  ]
}

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

ElasticSearch搜索结果处理_字段_04

2.2.深度分页问题

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

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

ElasticSearch搜索结果处理_字段_05

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

2.3.深度分页解决方案

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

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

注意:

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

2.4.案例说明:

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

ElasticSearch搜索结果处理_字段_06

2.5.总结

1)from+size:

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

2)after search:

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

3)scroll:

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

三、高亮

3.1.高亮原理说明

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

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

以百度搜索如下:

ElasticSearch搜索结果处理_字段_07

3.2.语法说明

GET /hotel/_search
{
  "query": {
    "match": {
      "FIELD": "TEXT"
    }
  },
  "highlight": {
    "fields": { //指定要高亮的字段
      "FIELD":{
        "pre_tags": "<em>",//用来标记高亮字段的前置标签
        "post_tags": "</em>"//用来标记高亮字段的后置标签
      }
    }
  }
}

注意:

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

3.3.案例

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

GET /hotel/_search
{
  "query": {
    "match": {
      "all": "如家"
    }
  },
  "highlight": {
    "fields": {
      "name": {"require_field_match": "false"}
    }
  }
}

执行后如下:

ElasticSearch搜索结果处理_数据_08

四、搜索结果整体处理

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

GET /hotel/_search
{
  "query": {
    "match": {
      "name": "如家"
    }
  },
  "from": 0,//分页开始的位置
  "size": 20,//期望获取的文档总数
  "sort": [
    {"price": "desc"},//普通排序,升序
    {"_geo_distance": {//按照距离排序
      "location": {
        "lat": 31.196955,
        "lon": 121.339752
      },
      "order": "asc",
      "unit": "km"
    }}
  ],
  "highlight": {
    "fields": {//高亮字段
      "name": {
        "pre_tags": "<em>",//用来标记高亮字段的前置标签
        "post_tags": "</em>"//用来标记高亮字段的后置标签
      }
    }
  }
}

执行后结果如下:

ElasticSearch搜索结果处理_字段_09



标签:search,高亮,分页,处理,查询,搜索,ElasticSearch,排序,ES
From: https://blog.51cto.com/u_13661275/8613017

相关文章

  • 处理挖矿病毒kthreaddk的过程
    问题描述发现服务器的CPU和内存占用非常高,然后看了一下发现有几个异常的程序PIDUSERPRNIVIRTRESSHRS%CPU%MEMTIME+COMMAND12043root......
  • ElasticSearch之线程池
    ElasticSearch节点可用的CPU核的数量,通常可以交给ElasticSearch来自行检测和判定,另外可以在``elasticsearch.yml`中显式指定。样例如下:node.processors:2如下表格中的processors即CPU核的数量。线程池的列表线程池名称类型线程数量队列长度用途genericscaling......
  • ElasticSearch之cat nodes API
    命令样例如下:curl-XGET"https://localhost:9200/_cat/nodes?v=true&pretty"--cacert$ES_HOME/config/certs/http_ca.crt-u"elastic:ohCxPH=QBE+s5=*lo7F9"执行结果输出如下:ipheap.percentram.percentcpuload_1mload_5mload_15mnode.role......
  • ElasticSearch之cat nodeattrs API
    命令样例如下:curl-XGET"https://localhost:9200/_cat/nodeattrs?v=true&pretty"--cacert$ES_HOME/config/certs/http_ca.crt-u"elastic:ohCxPH=QBE+s5=*lo7F9"执行结果输出如下:nodehostipattrvalu......
  • ElasticSearch之cat master API
    命令样例如下:curl-XGET"https://localhost:9200/_cat/master?v=true&pretty"--cacert$ES_HOME/config/certs/http_ca.crt-u"elastic:ohCxPH=QBE+s5=*lo7F9"执行结果输出如下:idhostipnodeaKgBu7LgS9a6iPYH8n2JPw1......
  • ElasticSearch之cat indices API
    命令样例如下:curl-XGET"https://localhost:9200/_cat/indices?v=true&pretty"--cacert$ES_HOME/config/certs/http_ca.crt-u"elastic:ohCxPH=QBE+s5=*lo7F9"执行结果输出如下:healthstatusindexuuidprirepdocs.coun......
  • Python常用的数据处理函数和模块
    Python还提供了许多其他用于数据处理和转换的内置函数和模块。以下是一些常用的数据处理函数和模块:sortedsorted(iterable,key=func,reverse=False)用于对可迭代对象进行排序。你可以指定一个可选的key函数来自定义排序规则,以及一个可选的reverse参数来控制升序或降序排......
  • app上架一直显示审核中状态要怎么处理?
    ​当你提交一个应用到AppStore上时,它会经历一个审核过程。在这个过程中,苹果的审核人员会检查你的应用是否符合苹果的规定和标准。这个过程通常需要几天的时间,但是如果你的应用一直显示“审核中”状态,那么可能会有一些原因。1.应用审核队列太长苹果的审核队列通常很长,这意味着......
  • iOS-打包上架构建版本一直不出现/正在处理/自动消失
    ​iOS开发过程中,打包上架苹果审核是一个不可或缺的环节。说实话,这个问题我遇见两次了,为了让自己长点记性,决定写下来。首先,列举几种情况:1.iPa包上传至Appstore后,一个小时内不显示构建版本。(等待15分钟-25分钟是正常的)   ​ 2.“活动”栏目下,所有构建版本长时间显示“......
  • Elasticsearch query查询语法 es
    Elasticsearch查询语法1.查询基本语法结构GET/{索引名}/_search{ "from":0,//返回搜索结果的开始位置 "size":10,//分页大小,一次返回多少数据 "_source":[...需要返回的字段数组...], "query":{...query子句...}, "aggs":{..aggs子句..},......