ElasticSearch 搜索、排序、分页功能

一、DSL 查询文档

ElasticSearch 的查询依然是基于 json 风格的 DSL 来实现的。

官方文档:https://www.elastic.co/guide/en/elasticsearch/reference/8.15/query-dsl.html

1.1 DSL 查询分类

常见的查询类型包括:

  • 查询所有:查询出所有数据,一般测试用。如:
    • match_all
  • 全文检索(full text)查询:利用分词器对用户输入内容分词,然后去倒排索引库中匹配,如:
    • match
    • multi_match
  • 精确查询:根据精确词条值查找数据,一般是查找keyword、数值、日期、boolean等类型字段。如:
    • ids
    • range
    • term、terms
  • 地理(geo)查询:根据经纬度查询,如:
    • geo_distance
    • geo_bounding_box
  • 复合(compound)查询:复合查询可以将上述各种查询条件组合起来,合并查询条件。如:
    • bool
    • function_score

1.2 DSL 基本语法

GET /索引库/_search
{
	"query":{
		"查询类型":{
			"查询字段": "值"
		}
	}
}

查询所有,示例:

GET /hotel/_search
{
	"query":{
		"match_all":{}
	}
}

查询“速8”酒店,示例:

GET /hotel/_search
{
  "query":{
    "match": {
      "name": "速8"
    }
  }
}

二、全文检索查询

2.1 使用场景

  • 商城的输入框搜索
  • 百度输入框搜索

2.2 基本流程

  • 对用户搜索的内容做分词,得到词条
  • 根据词条去倒排索引库中匹配,得到文档id
  • 根据文档id找到文档,返回给用户

说明:因为是拿着词条去匹配,因此参与搜索的字段也必须是可分词的 tex t类型的字段。

2.3 基本语法

常见的全文检索查询包括:

  • match 查询:单字段查询
  • multi_match查询:多字段查询,任意一个字段符合条件就算符合查询条件;字段越多,性能越差。

match 基本语法:

GET /索引名/_search
{
  "query": {
    "match": {
      "FIELD": "TEXT"
    }
  }
}

kibanna 测试示例:

GET /hotel/_search
{
  "query":{
    "match": {
      "name": "速8"
    }
  }
}

# 响应结果:
{"took":4,"timed_out":false,"_shards":{"total":1,"successful":1,"skipped":0,"failed":0},"hits":{"total":{"value":15,"relation":"eq"},"max_score":5.8927264,"hits":[{"_index":"hotel","_id":"1637944903","_score":5.8927264,"_source":{"id":1637944903,"name":"速8酒店北京后海店","address":"西城北京市西城区德胜门内大街兴华胡同五福里2号","price":213,"score":39,"brand":"速8","city":"北京","starName":"二钻","business":"后海","location":"39.934452,116.38184","pic":"https://m.tuniucdn.com/fb2/t1/G1/M00/48/0C/Cii9EVk1JNuILdBWAAHv5O89TjMAALrFgJ8bwcAAe_8197_w200_h200_c1_t0.jpg"}},{"_index":"hotel","_id":"38609","_score":5.5926995,"_source":{"id":38609,"name":"速8酒店(上海赤峰路店)","address":"广灵二路126号","price":249,"score":35,"brand":"速8","city":"上海","starName":"二钻","business":"四川北路商业区","location":"31.282444,121.479385","pic":"https://m.tuniucdn.com/fb2/t1/G2/M00/DF/96/Cii-TFkx0ImIQZeiAAITil0LM7cAALCYwKXHQ4AAhOi377_w200_h200_c1_t0.jpg"}},{"_index":"hotel","_id":"711837","_score":5.3217444,"_source":{"id":711837,"name":"速8酒店(北京立水桥店)","address":"朝阳安立路3号1幢3层","price":268,"score":36,"brand":"速8","city":"北京","starName":"二钻","business":"亚运村、奥体中心地区","location":"40.043717,116.410962","pic":"https://m2.tuniucdn.com/filebroker/cdn/res/b3/87/b3876eaf16af62521cf6fb474504b8ca_w200_h200_c1_t0.jpg"}},{"_index":"hotel","_id":"197516492","_score":5.3217444,"_source":{"id":197516492,"name":"速8酒店(北京南苑东高地店)","address":"丰台南大红门路东营房15号","price":651,"score":39,"brand":"速8","city":"北京","starName":"二钻","business":"永定门、南站、大红门、南苑地区","location":"39.78996,116.42081","pic":"https://m.tuniucdn.com/fb2/t1/G1/M00/3B/D8/Cii-U1kxKGWIQlaxAAIdkjkSALkAALXDQMFbTsAAh2q158_w200_h200_c1_t0.jpg"}},{"_index":"hotel","_id":"197492277","_score":5.075831,"_source":{"id":197492277,"name":"速8酒店(北京平谷兴谷环岛店)","address":"平谷平谷大街31号","price":614,"score":39,"brand":"速8","city":"北京","starName":"二钻","business":"平谷城区","location":"40.159255,117.12401","pic":"https://m.tuniucdn.com/fb2/t1/G1/M00/38/D5/Cii9EFkwFCiII79zAAHKsXy_LAoAALQuQEmEZ4AAcrJ339_w200_h200_c1_t0.jpg"}},{"_index":"hotel","_id":"197496980","_score":5.075831,"_source":{"id":197496980,"name":"速8酒店(北京温都水城王府店)","address":"昌平北七家镇平西府村(温都水城东200米)","price":585,"score":39,"brand":"速8","city":"北京","starName":"二钻","business":"小汤山温泉度假区","location":"40.10144,116.380641","pic":"https://m.tuniucdn.com/fb2/t1/G2/M00/C7/CB/Cii-T1km_5eICnpJAAHOWN1GylMAAKYJwF0Hp8AAc5w000_w200_h200_c1_t0.jpg"}},{"_index":"hotel","_id":"47478","_score":4.8516397,"_source":{"id":47478,"name":"速8酒店(上海松江中心店)","address":"松江荣乐东路677号","price":428,"score":35,"brand":"速8","city":"上海","starName":"二钻","business":"佘山、松江大学城","location":"31.016712,121.261606","pic":"https://m.tuniucdn.com/filebroker/cdn/res/07/36/073662e1718fccefb7130a9da44ddf5c_w200_h200_c1_t0.jpg"}},{"_index":"hotel","_id":"5873072","_score":4.8516397,"_source":{"id":5873072,"name":"速8酒店(上海火车站北广场店)","address":"闸北芷江西路796号","price":190,"score":41,"brand":"速8","city":"上海","starName":"二钻","business":"上海火车站地区","location":"31.255579,121.452903","pic":"https://m2.tuniucdn.com/filebroker/cdn/res/96/6d/966d6596e6cb7b48c9cc1d7da79b57c8_w200_h200_c1_t0.jpg"}},{"_index":"hotel","_id":"197488318","_score":4.8516397,"_source":{"id":197488318,"name":"速8酒店(北京立水桥地铁南站店)","address":"朝阳北苑路18号院3号楼4层","price":344,"score":36,"brand":"速8","city":"北京","starName":"二钻","business":"亚运村、奥体中心地区","location":"40.043689,116.414138","pic":"https://m.tuniucdn.com/fb2/t1/G1/M00/36/4D/Cii9EVkvP72IYYjgAAF7yZeWV-wAALMQACOARMAAXvh983_w200_h200_c1_t0.jpg"}},{"_index":"hotel","_id":"234719728","_score":4.8516397,"_source":{"id":234719728,"name":"速8酒店(北京房山城关店)","address":"房山城关镇城隍庙街10号(原房山老公安局)","price":392,"score":47,"brand":"速8","city":"北京","starName":"二钻","business":"","location":"39.705216,115.981904","pic":"https://m.tuniucdn.com/fb2/t1/G1/M00/3F/66/Cii9EFkyeImIB3ZVAAHcTtTFt4oAALdsgICDO0AAdxm378_w200_h200_c1_t0.jpg"}}]}}

mulit_match 基本语法:

GET /indexName/_search
{
  "query": {
    "multi_match": {
      "query": "TEXT",
      "fields": ["FIELD1", " FIELD12"]
    }
  }
}

kibana 测试示例:

GET /hotel/_search
{
  "query":{
    "multi_match": {
      "query": "北京速8",
      "fields": ["name","city"]
    }
  }
}
# 响应结果:
{"took":18,"timed_out":false,"_shards":{"total":1,"successful":1,"skipped":0,"failed":0},"hits":{"total":{"value":67,"relation":"eq"},"max_score":7.23897,"hits":[{"_index":"hotel","_id":"1637944903","_score":7.23897,"_source":{"id":1637944903,"name":"速8酒店北京后海店","address":"西城北京市西城区德胜门内大街兴华胡同五福里2号","price":213,"score":39,"brand":"速8","city":"北京","starName":"二钻","business":"后海","location":"39.934452,116.38184","pic":"https://m.tuniucdn.com/fb2/t1/G1/M00/48/0C/Cii9EVk1JNuILdBWAAHv5O89TjMAALrFgJ8bwcAAe_8197_w200_h200_c1_t0.jpg"}},{"_index":"hotel","_id":"711837","_score":6.5375423,"_source":{"id":711837,"name":"速8酒店(北京立水桥店)","address":"朝阳安立路3号1幢3层","price":268,"score":36,"brand":"速8","city":"北京","starName":"二钻","business":"亚运村、奥体中心地区","location":"40.043717,116.410962","pic":"https://m2.tuniucdn.com/filebroker/cdn/res/b3/87/b3876eaf16af62521cf6fb474504b8ca_w200_h200_c1_t0.jpg"}},{"_index":"hotel","_id":"197516492","_score":6.5375423,"_source":{"id":197516492,"name":"速8酒店(北京南苑东高地店)","address":"丰台南大红门路东营房15号","price":651,"score":39,"brand":"速8","city":"北京","starName":"二钻","business":"永定门、南站、大红门、南苑地区","location":"39.78996,116.42081","pic":"https://m.tuniucdn.com/fb2/t1/G1/M00/3B/D8/Cii-U1kxKGWIQlaxAAIdkjkSALkAALXDQMFbTsAAh2q158_w200_h200_c1_t0.jpg"}},{"_index":"hotel","_id":"197492277","_score":6.235448,"_source":{"id":197492277,"name":"速8酒店(北京平谷兴谷环岛店)","address":"平谷平谷大街31号","price":614,"score":39,"brand":"速8","city":"北京","starName":"二钻","business":"平谷城区","location":"40.159255,117.12401","pic":"https://m.tuniucdn.com/fb2/t1/G1/M00/38/D5/Cii9EFkwFCiII79zAAHKsXy_LAoAALQuQEmEZ4AAcrJ339_w200_h200_c1_t0.jpg"}},{"_index":"hotel","_id":"197496980","_score":6.235448,"_source":{"id":197496980,"name":"速8酒店(北京温都水城王府店)","address":"昌平北七家镇平西府村(温都水城东200米)","price":585,"score":39,"brand":"速8","city":"北京","starName":"二钻","business":"小汤山温泉度假区","location":"40.10144,116.380641","pic":"https://m.tuniucdn.com/fb2/t1/G2/M00/C7/CB/Cii-T1km_5eICnpJAAHOWN1GylMAAKYJwF0Hp8AAc5w000_w200_h200_c1_t0.jpg"}},{"_index":"hotel","_id":"197488318","_score":5.960038,"_source":{"id":197488318,"name":"速8酒店(北京立水桥地铁南站店)","address":"朝阳北苑路18号院3号楼4层","price":344,"score":36,"brand":"速8","city":"北京","starName":"二钻","business":"亚运村、奥体中心地区","location":"40.043689,116.414138","pic":"https://m.tuniucdn.com/fb2/t1/G1/M00/36/4D/Cii9EVkvP72IYYjgAAF7yZeWV-wAALMQACOARMAAXvh983_w200_h200_c1_t0.jpg"}},{"_index":"hotel","_id":"234719728","_score":5.960038,"_source":{"id":234719728,"name":"速8酒店(北京房山城关店)","address":"房山城关镇城隍庙街10号(原房山老公安局)","price":392,"score":47,"brand":"速8","city":"北京","starName":"二钻","business":"","location":"39.705216,115.981904","pic":"https://m.tuniucdn.com/fb2/t1/G1/M00/3F/66/Cii9EFkyeImIB3ZVAAHcTtTFt4oAALdsgICDO0AAdxm378_w200_h200_c1_t0.jpg"}},{"_index":"hotel","_id":"1714520967","_score":5.960038,"_source":{"id":1714520967,"name":"速8酒店(北京安华桥黄寺大街店)","address":"黄寺大街12号院16号楼","price":559,"score":43,"brand":"速8","city":"北京","starName":"二钻","business":"马甸、安贞地区","location":"39.962742,116.388431","pic":"https://m.tuniucdn.com/fb2/t1/G1/M00/4A/21/Cii-U1k1o-uIdcUZAAIbmIKVlKAAALtvQGBb6kAAhuw170_w200_h200_c1_t0.jpg"}},{"_index":"hotel","_id":"706343","_score":5.7079287,"_source":{"id":706343,"name":"速8酒店(北京西客站北广场店)","address":"丰台莲花池东路126号","price":268,"score":39,"brand":"速8","city":"北京","starName":"二钻","business":"北京西站、丽泽商务区","location":"39.896623,116.315586","pic":"https://m.tuniucdn.com/fb2/t1/G2/M00/E3/46/Cii-TlkzMXWIL0sAAAGG8a3YwiwAALJlgG-r5YAAYcJ067_w200_h200_c1_t0.jpg"}},{"_index":"hotel","_id":"38609","_score":5.5926995,"_source":{"id":38609,"name":"速8酒店(上海赤峰路店)","address":"广灵二路126号","price":249,"score":35,"brand":"速8","city":"上海","starName":"二钻","business":"四川北路商业区","location":"31.282444,121.479385","pic":"https://m.tuniucdn.com/fb2/t1/G2/M00/DF/96/Cii-TFkx0ImIQZeiAAITil0LM7cAALCYwKXHQ4AAhOi377_w200_h200_c1_t0.jpg"}}]}}

前面我们将 brand、name、business 值利用 copy_to 复制到了 all 字段中,比较
match + all 与 multi_match brand,name,business查询结果:
在这里插入图片描述
在这里插入图片描述
通过比较,我们发现两次的查询结果是一样的。但是,搜索字段越多,对查询性能影响越大,因此建议采用 copy_to,然后单字段查询的方式。

三、精确查询

精确查询一般是查找 keyword、数值、日期、boolean 等类型字段。所以不会对搜索条件分词。

常见的全文检索查询包括:

  • term:根据词条精确值查询
  • range:根据值的范围查询

3.1 term 查询

说明:

  • 因为精确查询的字段搜是不分词的字段,因此查询的条件也必须是不分词的词条。
  • 用户输入的内容跟文档值完全匹配时才认为符合条件。

基本语法:

GET /索引库/_search
{
  "query":{
    "term": {
      "FIELD": {
        "value": "VALUE"
      }
    }
  }
}

Kibana 测试:
在这里插入图片描述

3.2 range 查询

范围查询,一般应用在对数值、日期类型做范围过滤。

基本语法:

GET /索引库/_search
{
  "query": {
    "range": {
      "FIELD": {
        "gte": 10,
        "lte": 20
      }
    }
  }
}

Kibana 测试:
在这里插入图片描述

四、地理坐标查询

所谓的地理坐标查询,其实就是根据经纬度查询。

常见的使用场景:

  • 搜索我附近的酒店
  • 搜索我附近的出租车
  • 搜索我附近的人

4.1 geo_bounding_box 矩形范围查询

说明:指定矩形的左上、右下两个点的坐标,然后画出一个矩形,落在该矩形内的都是符合条件的点。
基本语法:

GET /hotel/_search
{
  "query": {
    "geo_bounding_box": {
      "FIELD": {
        "top_left": {
          "lat": 40.73,
          "lon": -74.1
        },
        "bottom_right": {
          "lat": 40.717,
          "lon": -73.99
        }
      }
    }
  }

Kibana 测试:
在这里插入图片描述

4.2 geo_distance 距离查询

说明:查询到指定中心点小于某个距离值的所有文档。换句话来说,在地图上找一个点作为圆心,以指定距离为半径,画一个圆,落在圆内的坐标都算符合条件。

基本语法:

GET /hotel/_search
{
  "query": {
    "geo_distance": {
      "distance": "10km", 	// 半径
      "FIELD": { 			// 圆心
        "lat": 40.73,		// 纬度
        "lon": -74.1		// 经度
      }
    }
  }
}

Kibana 测试:
在这里插入图片描述

五、compound 复合查询

说明:复合查询可以将其它简单查询组合起来,实现更复杂的搜索逻辑。常见的有两种:

  • bool 查询:布尔查询,利用逻辑关系组合多个其它的查询,实现复杂搜索
  • function_score 查询:算分函数查询,可以控制文档相关性算分,控制文档排名

相关性算分:
当我们利用match查询时,文档结果会根据与搜索词条的关联度打分(_score),返回结果时按照分值降序排列。
在这里插入图片描述
BM25 算法公式(5.1+):
在这里插入图片描述

5.1 bool 查询

布尔查询是一个或多个查询子句的组合,每一个子句就是一个子查询。

子查询的组合方式有:

  • must:必须匹配每个子查询,类似 “与” 查询
  • should:选择性匹配子查询,类似 “或” 查询
  • must_not:必须不匹配,类似 “非” 查询,不参与算分
  • filter:必须匹配,不参与算分

说明:参与打分的字段越多,查询性能越差。

建议:

  • 搜索框的关键字搜索,是全文检索查询,使用 must 查询,参与算分
  • 其它过滤条件,采用filter查询。不参与算分

语法示例:

POST /索引库/_search
{
  "query": {
    "bool" : {
      "must" : {
        "term" : { "user.id" : "kimchy" }
      },
      "filter": {
        "term" : { "tags" : "production" }
      },
      "must_not" : {
        "range" : {
          "age" : { "gte" : 10, "lte" : 20 }
        }
      },
      "should" : [
        { "term" : { "tags" : "env1" } },
        { "term" : { "tags" : "deployed" } }
      ],
      "minimum_should_match" : 1
    }
  }
}

测试示例1:
需求:搜索名字包含“如家”,价格不高于 400,在坐标 31.21,121.5 周围 10km 范围内的酒店。

分析:

  • 名称搜索,属于全文检索查询,应该参与算分。放到 must 中
  • 价格不高于400,用 range 查询,属于过滤条件,不参与算分。放到 must_not 中
  • 周围 10km 范围内,用 geo_distance 查询,属于过滤条件,不参与算分。放到filter中

语法结构:

GET /hotel/_search
{
  "query": {
    "bool": {
      "must": [
        {
          "match": {
            "name": "如家"
          }
        }
      ],
      "must_not": [
        {
          "range": {
            "price": {
              "gt": 400
            }
          }
        }
      ],
      "filter": [
        {
          "geo_distance": {
            "distance": "10km",
            "location": {
              "lat": 31.21,
              "lon": 121.5
            }
          }
        }
      ]
    }
  }
}

Kibana 测试:
在这里插入图片描述

5.2 function_score 算分函数查询

根据相关度打分是比较合理的需求,但合理的不一定是产品经理需要的。以百度为例,你搜索的结果中,并不是相关度越高排名越靠前,而是谁掏的钱多排名就越靠前。要想认为控制相关性算分,就需要利用 elasticsearch 中的 function_score 查询了。

5.2.1 function score 运行流程:

  1. 根据原始条件查询搜索文档,并且计算相关性算分,称为原始算分(query score)
  2. 根据过滤条件,过滤文档
  3. 符合过滤条件的文档,基于算分函数运算,得到函数算分(function score)
  4. 将原始算分(query score)和函数算分(function score)基于运算模式做运算,得到最终结果,作为相关性算分

5.2.2 相关性算分
当我们利用 match 查询时,文档结果会根据与搜索词条的关联度打分(_score),返回结果时按照分值降序排列。

例如,我们搜索 “如家”,结果如下:
在这里插入图片描述

5.2.3 ElasticSearch(5.1+) BM25 算法公式如下
在这里插入图片描述
5.2.4 function_score 查询语法:

  • query:原始查询条件,基于该条件搜索文档,并基于 BM25 算法为文档打分,所得结果即为原始分

  • functions: 算分函数,算分函数的结果称为 function score,结果将与 query score 运算,得到新算分。

    • 常见的算分函数有:

      • weight:给一个常量值,作为函数结果
      • field_value_factor:用文档中的某个字段值,作为函数结果
      • random_score:随机生成一个值,作为函数结果
      • script_score:自定义计算公式,作为函数结果
    • filter:过滤条件,符合该条件的文档才会重新算分

  • boost_mode:运算模式,算分函数的结果,原始查询的相关性算分,两者之间的运算方式。

    • 常见的运算方式有:
      - multiply:两者相乘(默认)
      - replace:用 function score 替代 query score
      - 其他: sum、avg、max、min

5.2.5 基本语法格式
其他可选参数,可访问官网进行学习。官网地址:https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-function-score-query.html

GET /_search
{
  "query": {
    "function_score": {
      "query": { "match_all": {} },
      "functions": [
        {
          "filter": { "match": { "test": "cat" } },
          "weight": 42
        }
      ],
      "boost_mode": "multiply"
    }
  }
}

5.2.6 测试示例
需求:给价格小于300品牌为“如家”的酒店,排名靠前一些。
整理:

  • 原始条件:价格小于300
  • 过滤条件:品牌为“如家”
  • 算法函数:按需指定,本次就直接固定加分(weight)
  • 运算模式:求和

直接查询查询价格小于300的酒店:

在这里插入图片描述
从图上我们可以看出,直接查询“速8”的酒店靠前。

使用算法函数查询:

定义 DSL 语法:

GET /hotel/_search
{
  "query": {
    "function_score": {
      "query": {
        "range": {
          "price": {
            "lte": 300
          }
        }
      },
      "functions": [
        {
          "filter": {
            "term": {
              "brand": "如家"
            }
          },
          "weight": 2
        }
      ],
      "boost_mode": "sum"
    }
  }
}

测试结果:

在这里插入图片描述
从图中我们可以看出,“如家”酒店已经靠前,且算分结果也是正常加了2分。

六、排序

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

6.1 普通字段排序

DSL 语法

GET /hotel/_search
{
  "query": {
    "match_all": {}
  },
  "sort": [
    {
      "FIELD": {
        "order": "desc"
      }
    }
  ]
}

说明:支持多字段排序,第一个条件相同时,按第二个排序,以此类推。

案例:查询所有酒店,并按照评分高的在前,价格低的在前
定义 DSL 语法

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

测试结果
在这里插入图片描述

6.2 地理坐标排序

DSL 语法

GET /hotel/_search
{
  "query": {
    "match_all": {}
  },
  "sort": [
    {
      "_geo_distance": {
        "FIELD": {
          "lat": 40, // 纬度
          "lon": -70 // 经度
        },
        "order": "asc",
        "unit": "km"
      }
    }
  ]
}

案例:根据自己的位置按照酒店离你的位置升序排序
查询定位网址:https://map.bmcx.com/jingwei_dr__map/
定义 DSL 语法

GET /hotel/_search
{
  "query": {
    "match_all": {}
  },
  "sort": [
    {
      "_geo_distance": {
        "location": {
          "lat": 31.264845, // 纬度
          "lon": 121.658846 // 经度
        },
        "order": "asc",
        "unit": "km"
      }
    }
  ]
}

测试结果:
在这里插入图片描述

七、分页

ElasticSearch 默认情况下只返回10条数据,如果要查询更多数据就需要修改分页参数。

  • from:从第几个文档开始,类似 mysql 的 offset
  • size:查询几个文档,类似 mysql 的 limit

7.1 基本语法

DSL 语法

GET /hotel/_search
{
  "query": {
    "match_all": {}
  },
  "sort": [
    {
      "score": {
        "order": "desc"
      }
    }
  ], 
  "from": 0, 
  "size": 10
}

测试结果:
在这里插入图片描述

7.2 深度分页问题

需求:查询 990 ~ 1000的数据,查询 9900 ~ 10000的数据

问题
ElasticSearch 内部分页时,必须先查询 0~1000 条,然后截取其中的 990 ~ 1000的这 10 条数据。
如果 ES 是单点模式,这并无太大影响。如果是多集群部署,我需要根据条件排序后 查询出 1000 数据,假如有5台节点,并不是每个节点取 200条数据,因为 节点1 的 Top 200,在另一个节点可能排到 10000 名以外了。因此,要想获取整个集群的 Top 1000,必须先查询出每个节点的 Top 1000,汇总结果后,重新排名,重新截取 Top 1000。
那如果我要查询 9900~10000 的数据呢?是不是要先查询 Top 10000 呢?每个节点都要查询 10000 条?汇总到内存中?
当查询分页深度较大时,汇总数据过多,对内存和 CPU 会产生非常大的压力,因此 ES 会禁止 from + size 超过 10000 的请求。

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

总结

  • from + size

    • 优点:支持随机翻页
    • 缺点:深度分页问题,默认查询上限(from + size)是10000
  • after search

    • 优点:没有查询上限(单次查询的size不超过10000)
    • 缺点:只能向后逐页查询,不支持随机翻页
  • scroll(不推荐)

    • 优点:没有查询上限(单次查询的size不超过10000)
    • 缺点:会有额外内存消耗,并且搜索结果是非实时的

八、高亮显示

DSL 基础语法

GET /hotel/_search
{
  "query": {
    "match": {
      "name": "如家" // 必须指定搜索条件
    }
  },
  "sort": [
    {
      "score": {
        "order": "desc"
      }
    },
    {
      "price": {
        "order": "asc"
      }
    }
  ], 
  "from": 0,
  "size":10,
  "highlight":{
    "fields": {
      "name":{
        "pre_tags": "<em>", // 用来标记高亮字段的前置标签,默认:<em>
        "post_tags": "</em>" // 用来标记高亮字段的后置标签,默认:</em>
      }
    }
  }
}

说明:

  • 高亮是对关键字高亮,因此搜索条件必须带有关键字,而不能是范围这样的查询。
  • 默认情况下,高亮的字段,必须与搜索指定的字段一致,否则无法高亮
  • 如果要对非搜索字段高亮,则需要添加一个属性:required_field_match=false

非搜索字段高亮设置:
DSL 基础语法:

GET /hotel/_search
{
  "query": {
    "match": {
      "all": "如家" // all: name,brand等字段的集合
    }
  },
  "highlight":{
    "fields": {
      "name": {
        "require_field_match": "false" // 虽然查询条件没有指定 name 字段,但是这边 require_field_match 设置成 false ,则也可以高亮显示
      },
      "brand": {
        "require_field_match": "false"
      }
    }
  }
}

测试结果:
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/935540.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

mybatis常见错误

1.没有在mybatis.xml里面引入映射文件 2. 连接数据库部分有误 3.控制台输出无误&#xff0c;数据库里只插入了id sql语句有误 正确 <insert id"add" useGeneratedKeys"true" keyProperty"id">insert into t_teacher values (null,#{nam…

GLM-4-Plus初体验

引言&#xff1a;为什么高效的内容创作如此重要&#xff1f; 在当前竞争激烈的市场环境中&#xff0c;内容创作已成为品牌成功的重要支柱。无论是撰写营销文案、博客文章、社交媒体帖子&#xff0c;还是制作广告&#xff0c;优质的内容不仅能够帮助品牌吸引目标受众的注意力&a…

Mac/Windows端长期破解myBase8方法(无需安装火绒)

提醒 不管哪个端&#xff0c;都需要先退出myBase。 Mac 进入用户根目录/Users/c0ny100&#xff0c;即下边是Macintosh HD > 用户 > [你的用户名]这个界面然后按ShiftCommond.&#xff0c;显示隐藏文件。找到.Mybase8.ini文件 打开.Mybase8.ini文件&#xff0c;删除Fir…

Capture绘制元器件(Candance 17.4)

step1&#xff1a;新建元器件库 step2&#xff1a;新建元器件 step3&#xff1a;新建元器件,填写元器件名称以及类型 step4&#xff1a;绘制元器件形状 step5&#xff1a;添加引脚 添加引脚名称以及序号 将GND、VIN等电源属性引脚从Passive改为Power&#xff0c;其余为Passive …

支持自定义离线地图地理区域,查询组件及数据源功能增强,DataEase开源BI工具v2.10.3 LTS发布

2024年12月9日&#xff0c;人人可用的开源BI工具DataEase正式发布v2.10.3 LTS版本。 这一版本的功能变动包括&#xff1a;数据源方面&#xff0c;API数据源和Excel数据源支持对字段类型和长度进行设置&#xff1b;图表方面&#xff0c;离线类地图支持自定义地理区域设置&#…

【Unity学习笔记·第十二】Unity New Input System 及其系统结构和源码浅析

转载请注明出处&#xff1a;&#x1f517;https://blog.csdn.net/weixin_44013533/article/details/132534422 作者&#xff1a;CSDN|Ringleader| 主要参考&#xff1a; 官方文档&#xff1a;Unity官方Input System手册与API官方测试用例&#xff1a;Unity-Technologies/InputS…

STM32F103单片机HAL库串口通信卡死问题解决方法

在上篇文章 STM32F103单片机使用STM32CubeMX创建IAR串口工程 中分享了使用cubeMX直接生成串口代码的方法&#xff0c;在测试的过程中无意间发现&#xff0c;串口会出现卡死的问题。 当串口一次性发送十几个数据的时候&#xff0c;串口感觉像卡死了一样&#xff0c;不再接收数据…

【指南】03 CSC联系外导

确定外导 课题组有合作关系的国外导师与自己研究方向密切相关的国外导师国外高校官网、谷歌学术、Research Gate等平台检索不可以是中国港澳台的高校科研院所或机构注意外导所在高校排名和科研水平可列表记录注意外国签证政策 发送邮件 自我介绍简要介绍CSC介绍自己的研究对…

umi实现动态获取菜单权限

文章目录 前景登录组件编写登录逻辑菜单的时机动态路由页面刷新手动修改地址 前景 不同用户拥有不同的菜单权限&#xff0c;现在我们实现登录动态获取权限菜单。 登录组件编写 //当我们需要使用dva的dispatch函数时&#xff0c;除了通过connect函数包裹组件还可以使用这种方…

swagger-codegen

一、通过Swagger生成客户端代码 下载&#xff1a;https://github.com/swagger-api/swagger-codegen#编译打包 cd E:\软件空间\代码生成\swagger-codegen-3.0.64 mvn clean package#指定swagger地址生成客户端代码 cd E:\软件空间\代码生成\swagger-codegen-3.0.64\modules\swa…

Kael‘thas Sunstrider Ashes of Al‘ar

Kaelthas Sunstrider 凯尔萨斯逐日者 <血精灵之王> Kaelthas Sunstrider - NPC - 魔兽世界怀旧服TBC数据库_WOW2.43数据库_70级《燃烧的远征》数据库 Ashes of Alar 奥的灰烬 &#xff08;凤凰 310%速度&#xff09; Ashes of Alar - Item - 魔兽世界怀旧服TBC数据…

7.Vue------$refs与$el详解 ------vue知识积累

$refs 与 $el是什么&#xff1f; 作用是什么? ref&#xff0c;$refs&#xff0c;$el &#xff0c;三者之间的关系是什么&#xff1f; ref (给元素或者子组件注册引用信息) 就像你要给元素设置样式&#xff0c;就需要先给元素设定一个 class 一样&#xff0c;同理&#xff0c;…

医院门诊预约挂号管理系统设计与实现

文末获取源码和万字论文&#xff0c;制作不易&#xff0c;感谢点赞支持。 医院门诊预约挂号管理系统设计与实现 摘 要 本医院门诊预约挂号管理系统是针对目前医院门诊预约挂号管理的实际需求&#xff0c;从实际工作出发&#xff0c;对过去的医院门诊预约挂号管理系统存在的问题…

学习记录,泛型界限1

泛型界限 上限 泛型的上限&#xff0c;下限。对类型的更加具体的约束&#xff01; 如果给某个泛型设置了上界&#xff1a;这里的类型必须是上界 如果给某个泛型设置了下界&#xff1a;这里的类型必须是下界

OpenAI直播发布第4天:ChatGPT Canvas全面升级,免费开放!

大家好&#xff0c;我是木易&#xff0c;一个持续关注AI领域的互联网技术产品经理&#xff0c;国内Top2本科&#xff0c;美国Top10 CS研究生&#xff0c;MBA。我坚信AI是普通人变强的“外挂”&#xff0c;专注于分享AI全维度知识&#xff0c;包括但不限于AI科普&#xff0c;AI工…

[工具升级问题] 钉钉(linux版)升级带来的小麻烦

本文由Markdown语法编辑器编辑完成。 1. 背景: 今日钉钉又发布了新的升级版本。由于我工作时使用的是Ubuntu 20.04版本&#xff0c;收到的升级推送信息是&#xff0c;可以升级到最新的7.6.25-Release版本。根据钉钉官方给出的历次更新版说明&#xff0c;这个新的版本&#xf…

DPDK用户态协议栈-TCP Posix API 2

tcp posix api send发送 ssize_t nsend(int sockfd, const void *buf, size_t len, __attribute__((unused))int flags) {ssize_t length 0;void* hostinfo get_host_fromfd(sockfd);if (hostinfo NULL) {return -1;}struct ln_tcp_stream* stream (struct ln_tcp_stream…

【网络开发-socket编程】

1 socket 简介 socket&#xff08;套接字&#xff09;是linux下的一种进程间通信机制&#xff0c;使用socket的IPC可以使得不同主机之间通信&#xff0c;也可以是同一台主机的不同程序之间。socket通常是客户端<------>服务端的通信模式&#xff0c;多个客户端可以同时连…

Python实现中国象棋

探索中国象棋 Python 代码实现&#xff1a;从规则逻辑到游戏呈现 中国象棋&#xff0c;这款源远流长的棋类游戏&#xff0c;承载着深厚的文化底蕴与策略智慧。如今&#xff0c;借助 Python 与 Pygame 库&#xff0c;我们能够在数字世界中复刻其魅力&#xff0c;深入探究代码背后…

TensorFlow深度学习实战(1)——神经网络与模型训练过程详解

TensorFlow深度学习实战&#xff08;1&#xff09;——神经网络与模型训练过程详解 0. 前言1. 神经网络基础1.1 神经网络简介1.2 神经网络的训练1.3 神经网络的应用 2. 从零开始构建前向传播2.1 计算隐藏层节点值2.2 应用激活函数2.3 计算输出层值2.4 计算损失值2.4.1 在连续变…