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 运行流程:
- 根据原始条件查询搜索文档,并且计算相关性算分,称为原始算分(query score)
- 根据过滤条件,过滤文档
- 符合过滤条件的文档,基于算分函数运算,得到函数算分(function score)
- 将原始算分(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"}}}
}
测试结果:
相关文章:
ElasticSearch 搜索、排序、分页功能
一、DSL 查询文档 ElasticSearch 的查询依然是基于 json 风格的 DSL 来实现的。 官方文档:https://www.elastic.co/guide/en/elasticsearch/reference/8.15/query-dsl.html 1.1 DSL 查询分类 常见的查询类型包括: 查询所有:查询出所有数…...
MAC虚拟机上安装WDA环境
MAC虚拟机上安装WDA环境 一、MAC虚拟机切换root权限二、macOS上安装xcode若你的macOS系统可以在appstore下载安装若你安装的macOS系统版本太低,无法在appstore上安装xcode 三、macOS上安装WebDriverAgent四、使用xcode配置WDA安装到手机上高版本系统支持 一、MAC虚拟…...
KDD 2025预讲会:10位一作的论文分享与话题思辨|12月18日全天直播
点击蓝字 关注我们 AI TIME欢迎每一位AI爱好者的加入! 圆桌思辨:一作们的KDD 2025投稿经验分享与热点探讨 1. KDD 2025 与往年相比有哪些新变化?两次投稿周期的新规则有哪些影响? 2. 第一篇KDD的工作是如何成功被接收的࿱…...
Input system手游的控制
手游离不开触屏控制 新的inputsystem 实现过程 安装input system在projectsetting中的player的othersettings中active input handing设置both打开window的analysis的input debugger。在options中设置为simulate touch input from mouse or pen。 增强触摸控制的相关知识 启…...
在 Visual Studio Code 中编译、调试和执行 Makefile 工程 llama2.c
在 Visual Studio Code 中编译、调试和执行 Makefile 工程 llama2.c 1. Installing the extension (在 Visual Studio Code 中安装插件)1.1. Extensions for Visual Studio Code1.2. C/C1.2.1. Pre-requisites 1.3. Makefile Tools 2. Configuring your project (配置项目)2.1.…...
KMP 算法
这里写目录标题 KMP数组计算方式**问题描述****初始准备****逐步推导过程****Step 1: i 1,子串为 ab****Step 2: i 2,子串为 aba****Step 3: i 3,子串为 abab****Step 4: i 4,子串为 ababa****Step 5: i 5,子串为…...
计算机网络中的三大交换技术详解与实现
目录 计算机网络中的三大交换技术详解与实现1. 计算机网络中的交换技术概述1.1 交换技术的意义1.2 三大交换技术简介 2. 电路交换技术2.1 理论介绍2.2 Python实现及代码详解2.3 案例分析 3. 分组交换技术3.1 理论介绍3.2 Python实现及代码详解3.3 案例分析 4. 报文交换技术4.1 …...
echarts图表自定义配置(二)——代码封装
下图是初版,火山图的代码。可以看出,里面的变量,逻辑,函数存在冗余,基本上都是改了参数,同样的get和set,去刷新图表;对于往后继续开发十几二十个图表,会很麻烦。因此需要…...
Serdes技术与Xilinx GT概览
目录 一、前言 二、Serdes技术 2.1 芯片间信号传输 2.2 Serdes技术 三、 Xilinx GT 3.1 7系列器件GT 3.2 Ultrascale GT 3.3 Ultrascale GT 四、参考资料 一、前言 对于芯片间高速信号传输技术,不得不提serdes以及在Xilinx在此基础上的高速收发器GT系列&…...
WEB开发: Node.js路由之由浅入深(三)自动配置路由 - 全栈工程师入门
前面我们一起学习了Node.js路由的两个进阶, (1)WEB开发: Node.js路由之由浅入深(一) - 全栈工程师入门 (2)WEB开发: Node.js路由之由浅入深(二)…...
6-9 捕获 0 异常(1)
中断号的 处理是这样的。 1、 cpu 根据中断号 去中断向量表 去找 第几个 表。、 2、 而 中断向量表 的内容是 GDT 的选择子。 3、 由于使用是的 平坦模型,所以只需要 将具体的函数给到 中断向量表的 offset 字段就可以了。 接下来 就是 在 代码中定义 中断门的属…...
社区团购创新模式与新兴技术融合的深度探索:基于开源、AI 智能名片、2+1 链动模式与 S2B2C 商城小程序
摘要:本文聚焦于社区团购这一新兴零售业态,深入剖析其“线上预售,线下自提,以销定采,落地集配”的 16 字箴言所蕴含的商业逻辑。详细探讨在物流与信息流层面社区团购的独特优势,并在此基础上研究开源理念、…...
day45 198.打家劫舍 213.打家劫舍II 337.打家劫舍III
198.打家劫舍 相邻的房子不可以打劫,所以递推式需要考虑; 初始化也需要考虑,可以从两个方向入手 方向1:从后往前看,dp[i] dp[i-1] class Solution { public:int rob(vector<int>& nums) {if (nums.size(…...
SQL server学习02-使用T-SQL创建数据库
目录 一, 使用T-SQL创建数据库 1,数据库的存储结构 2,创建数据库的语法结构 1)使用T-SQL创建学生成绩管理数据库 二,使用T-SQL修改数据库 1,修改数据库的语法结构 1)修改学生成绩管理数…...
绘图方式集合
1. 流程图 1.1 PlantUML 代码绘制流程图 1.1.1 简介 1.1.2 网站 你可以使用以下网站来将 PlantUML 代码转换成可视化的流程图: PlantUML 官方网站 网站地址:https://plantuml.com/plantuml此网站提供了一个在线工具,可以直接输入 PlantUM…...
sqoop导入hdfs,hive
sqoop将mysql中的表导入到hdfs中 sqoop import \ > --connect jdbc:mysql://192.168.52.150/test \ > --username root \ > --password 123456 \ > --table emp \ > --delete-target-dir \ > --target-dir /sqoop_works/emp_1将数据导入hive中,首…...
C语言动态内存管理【进阶--5--】
文章目录 [toc] 动态内存管理一、作用即意义二、动态内存函数的介绍Ⅰ、malloc()函数、free()函数Ⅱ、calloc()函数Ⅲ、realloc()函数 三、常见的动态内存错误Ⅰ、对NULL指针的解引用操作Ⅱ、对动态开辟空间的越界访问Ⅲ、对非动态开辟的内存使用free释放Ⅳ、使用free释放动态开…...
Hadoop其四,片与块,MapReduce原理,Shuffle过程,Combiner
目录 一、关于片和块 二、MapReduce的原理 MapTask执行阶段 ReduceTask的执行流程: 三、Shuffle 过程 map端: reduce端: 环形缓冲区: 四、Combiner 【可有可无】 五、需要记忆的内容 一、关于片和块 假如我现在500M这样…...
引领未来的变革:15种前沿RAG技术及其应用探索
在现代人工智能领域,检索增强生成(RAG)技术逐渐成为推动各种应用的重要力量。这些技术通过结合信息检索与文本生成,能够更有效地处理和利用信息。本文将详细介绍15种前沿RAG技术及其具体应用实例,以帮助您更好地理解这…...
gradle在IDEA 中无法使用的启动守护线程的问题
最近打开一个比较早的项目,Gradle 配置没有问题,IDEA 打开Java项目却不能初始化守护线程,UI 上只能看到失败,看不到具体原因。 首先尝试了升级最新的gradle 版本8.11, 实际上这个版本在本地命令行都不能正常工作,没有…...
C++小白实习日记——Pollnet,Efvi,UDP,数据类型转换(上)
上周主要是熟悉了一下公司内部一些自定义结构体对应的数据类型,要求:读取文件,将文件中数据转化为定义的结构体中的数据类型,按照时间进行排序,用UDP发送数据;在另一台服务器上接收数据,按照定义…...
git安装教程(Git-2.38.1-64-bit)
目录 一、git下载 二、git安装 1.更改安装路径 2.安装组件 3.选择开始菜单文件夹 4.选择Git默认编辑器 5.决定初始化新项目(仓库)的主干名字 6.修改Git的环境变量 7.选择SSH执行文件 9.选择HTTPS后端传输 10.配置行尾符号转换 11.配置终端模…...
C# OpenCvSharp DNN 实现百度网盘AI大赛-表格检测第2名方案第三部分-表格方向识别
目录 说明 效果 模型 项目 编辑 代码 参考 下载 其他 说明 百度网盘AI大赛-表格检测的第2名方案。 该算法包含表格边界框检测、表格分割和表格方向识别三个部分,首先,ppyoloe-plus-x 对边界框进行预测,并对置信度较高的表格边界…...
selenium 验证码滑块对齐没有验证通过
描述: 最近使用seleniuim采集有滑块验证码的数据,遇到了移动滑块对齐后,还是无法通过验证,经过模拟真人多次移动、控制移动时间(避免过快)一番尝试后、最终通过模拟抖动得以解决 解决办法: 把yoffset的值改为-6~6的…...
【Neo4J】neo4j docker容器下的备份与恢复
文章目录 一. 官网说明1. 操作说明2. 注意事项 二. docker 容器化操作1. 导出(备份)停止容器执行备份 2. 导入(恢复)停止容器(如果未停止)执行导入 3. 启动容器 一. 官网说明 https://neo4j.com/docs/operations-manual/current/…...
Java实现雪花算法获取id
Java实现雪花算法获取id 在 Java 中实现雪花算法(Snowflake)时,通常会设计一个工具类来生成全局唯一的 ID。这个工具类可以封装雪花算法的逻辑,并提供简单的接口来生成 ID。 以下是一个完整的 Java 工具类实现雪花算法的例子&am…...
Leetcode1338:数组大小减半
题目描述: 给你一个整数数组 arr。你可以从中选出一个整数集合,并删除这些整数在数组中的每次出现。 返回 至少 能删除数组中的一半整数的整数集合的最小大小。 代码思路: 这个代码的目的是解决一个特定的问题:给定一个整数数…...
【系统思辨】分散注意
注意力在我们的日常生活和工作中扮演着至关重要的角色。注意力可以提高效率和准确性、减少错误和失误,提升学习效率,促进创造力。与此同时,各种各样的生活事件在分散我们的注意力,并且还有很多分散我们注意的手段,比如…...
微信小程序中 Echarts 的巧妙运用
一、引入 Echarts 的准备工作 在微信小程序中引入 Echarts 需要进行一系列的准备工作。首先,我们可以从 echarts 官网或 GitHub 上下载 echarts-for-weixin 项目。找到其中的 ec-canvas 文件夹,这个文件夹将是我们引入到微信小程序项目中的关键部分。 …...
opencv——图片矫正
图像矫正 图像矫正的原理是透视变换,下面来介绍一下透视变换的概念。 听名字有点熟,我们在图像旋转里接触过仿射变换,知道仿射变换是把一个二维坐标系转换到另一个二维坐标系的过程,转换过程坐标点的相对位置和属性不发生变换&a…...
Gate学习(7)引入体素源
一、从GitHub下载体素源模型源码 下载地址:BenAuer2021/Phantoms-for-Nuclear-Medicine-Imaging-Simulation:用于核医学成像应用的模型(闪烁显像、SPECT 和 PET) --- BenAuer2021/Phantoms-For-Nuclear-Medicine-Imaging-Simulat…...
腾讯微信Android面试题及参考答案(多张原理图)
Android 应用的启动流程如下: 当用户点击应用图标时,首先会通过 Launcher(桌面启动器)来响应这个操作。Launcher 本身也是一个 Android 应用,它运行在系统中,负责管理和显示桌面上的图标等信息。 系统会检查应用是否已经有进程存在。如果没有,就会通过 Zygote 进程来孵化…...
【Android】View的工作流程
View的工作流程 开始了解一下View的工作流程,就是measure、layout和draw。measure用来测量View的宽高,layout用来确定View的位置,draw则用来绘制View。这一讲我们来看看measure流程,measure流程分为View的measure流程和ViewGroup…...
Linux基础指令
使用 tab 键补全 我们敲的所有的 Linux 命令 , 都可以使用 tab 键来尝试补全 , 加快效率 . 使用 ctrl c 重新输入 如果命令或者目录敲错了 , 可以 ctrl c 取消当前的命令 . ls :列出当前目录中的文件和子目录 语法 : ls [ 选项 ] [ 目录或文…...
Gemini 2.0 Flash重磅发布:多模态AI大模型,赋能实时交互与智能助手新体验
点击访问 chatTools 免费体验GPT最新模型,包括o1推理模型、GPT4o、Claude、Gemini等模型! 在AI领域竞争日益激烈的今天,谷歌再次亮剑,推出了新一代至强AI大模型——Gemini 2.0 Flash。这款模型不仅具备强大的多模态输入输出能力&a…...
项目十二 杜甫作品问卷
【项目目标】 理解网格系统的原理。理解媒体查询的工作原理。【項目内容】 使用网格系统进行响应式网页设计。运用媒体查询对不同类型的设备应用不同的样式。【项目步骤】 Bootstrap 框架资源既可以直接从 CDN 服务商服务器中引入,也可以加入本地素材文件夹中给出的资…...
7_Sass Introspection 函数 --[CSS预处理]
Sass 的 Introspection 函数允许开发者检查和操作样式表的内部结构,包括选择器、属性、值等。这些函数提供了对编译过程中 Sass 文件内容的深入访问能力,使得更复杂的逻辑处理成为可能。以下是一些常用的 Sass Introspection 函数及其用法示例࿱…...
Qt:Q_GLOBAL_STATIC实现单例(附带单例使用和内存管理)
转载 https://blog.csdn.net/m0_71489826/article/details/142288179 前言 本文主要写Q_GLOBAL_STATIC实现单例以及单例的释放,网上很多教程只有单例的创建,但是并没有告诉我们单例的内存管理,这就很头疼。 正文 使用 Qt 的 Q_GLOBAL_STA…...
HTML/CSS总结
HTML 1.1 标题标签h 为了使网页更具有语义化,我们经常会在页面中用到标题标签,HTML提供了6个等级的标题,即 标题标签语义: 作为标题使用,并且依据重要性递减 其基本语法格式如下: <h1> 标题文本…...
字符串性能对比
效率(1) : String.indexOf与String.contains效率测试_string contains效率-CSDN博客 结论是前者效率高,源码里面conatins是使用indexof 在jdk8中contains直接调用的indexOf(其他版本没有验证),所以要说效率来说肯定是indexOf高,但contains也就多了一层方法栈,so 什…...
【漫话机器学习系列】005.神经网络的结构(architecture on the neural network)
神经网络(Neural Network)是一种模拟人脑神经系统的计算模型,由大量相互连接的神经元(节点)组成,广泛应用于深度学习和机器学习领域。以下是神经网络的基本结构及关键组成部分。 1. 神经网络的基本组成 一…...
关卡选择与布局器
unity布局管理器 使用unity布局管理器轻松对关卡选择进行布局。 实现过程 准备普通按钮button设置字体和对应的sprite设置父gameobject(levelbase) 再创建UI.image(selectbackground)布局背景和大小gameobject(grid…...
数据分析实战—房价特征关系
1.实战内容 (1) 读取房价特征关系表(house_price.npz)绘制离地铁站的距离与单位面积的房价的散点图,并对其进行分析; import pandas as pd import numpy as np import warnings warnings.filterwarnings(&…...
@ResponseBody详解
ResponseBody 是 Spring Framework 中的一种注解,用于表示返回的内容应该直接写入 HTTP 响应体,而不是通过视图解析器来渲染一个视图(如 JSP 页)。当你在控制器的方法上使用 ResponseBody 时,Spring 会将方法的返回值直…...
Harmony Next开发通过bindSheet绑定半模态窗口
示例概述 Harmony Next开发通过bindSheet绑定半模态窗口 知识点 半模态窗口父子组件传值 组件 LoginComponent Component struct LoginComponent {// Prop 父子单项绑定值Prop message:string // Link 父子双向绑定值Link userName:stringLink password:stringLink isSh…...
Redis--高并发分布式结构
目录 一、引言 二、redis 1.什么是redis? 三、基础概念 1.什么是分布式? 2.应用服务和数据库服务分离 3.负载均衡 4.分库分表 5.微服务架构 四、总结 一、引言 本篇文章就简单介绍一下什么是redis,以及一些关于高并发和分布式结构的…...
Day38 动态规划part06
322. 零钱兑换 如果求组合数就是外层for循环遍历物品,内层for遍历背包。 如果求排列数就是外层for遍历背包,内层for循环遍历物品。 这句话结合本题 大家要好好理解。 视频讲解:动态规划之完全背包,装满背包最少的物品件数是多少?| LeetCode:322.零钱兑换_哔哩哔哩_bilib…...
1.1 类型(types)
源码 types.rs文件源码: use euclid::{Point2D, Vector2D};//引用外部泛型/// 绘图中所有事物所使用的笛卡尔坐标系。The cartesian coordinate system used by everything in a drawing. #[derive(Debug, Copy, Clone, PartialEq, Eq, Ord, PartialOrd)] pub enu…...
PyTorch如何通过 torch.unbind 和torch.stack动态调整张量的维度顺序
笔者一篇博客PyTorch 的 torch.unbind 函数详解与进阶应用:中英双语中有一个例子如下: # 创建一个 3x2x2 的三维张量 x torch.tensor([[[1, 2], [3, 4]],[[5, 6], [7, 8]],[[9, 10], [11, 12]]])# 第一步:沿第 0 维分解为 3 个 2x2 张量 un…...
在 Node.js 中安装和使用 TensorFlow.js 的完整指南
在 Node.js 中安装和使用 TensorFlow.js 的完整指南 简介 TensorFlow.js 是一个开源的机器学习库,它允许在 JavaScript 环境中进行机器学习模型的开发和训练。本文将介绍如何在 Node.js 环境中安装和配置 TensorFlow.js。 环境准备 在开始之前,请确保…...