查询所有:查询出所有数据(match_all)
全文检索:利用分词器对用户输入内容分词,然后去倒排索引库中匹配
精确查询:根据精确词条值查找数据,一般是查找keyword,数值,boolean等字段
地理查询:根据经纬度查询
复合查询:复合查询可以将上述各种查询条件组合起来,合并查询条件
GET /indexName/_search
{
"query": {
"查询类型": {
"查询条件": "条件值"
}
}
}
match查询:全文检索的一种,会对用户输入的内容分词,然后去倒排索引库检索
GET /indexName/_search
{
"query": {
"match": {
"FIELD": "TEXT"
}
}
}
multi_match:与match查询类似,只不过允许同时查询多个字段
GET /indexName/_search
{
"query": {
"multi_match": {
"query": "TEXT",
"fields": ["FIELD1", " FIELD12"]
}
}
}
match与multi_match的区别
精确查询一般是查找keyword、数值、日期、boolean等类型字段,所以不会对搜索条件分词,常见的有:
trem查询语法:
// term查询
GET /indexName/_search
{
"query": {
"term": {
"FIELD": {
"value": "VALUE"
}
}
}
}
range查询语法:
// range查询
GET /indexName/_search
{
"query": {
"range": {
"FIELD": {
"gte": 10,
"lte": 20
}
}
}
}
根据经纬度查询
语法:
// geo_bounding_box查询
GET /indexName/_search
{
"query": {
"geo_bounding_box": {
"FIELD": {
//左上角
"top_left": {
"lat": 31.1,
"lon": 121.5
},
//右下角
"bottom_right": {
"lat": 30.9,
"lon": 121.7
}
}
}
}
}
语法:
// geo_distance 查询
GET /indexName/_search
{
"query": {
"geo_distance": {
"distance": "距离",
"FIELD": "经纬度坐标"
}
}
}
复合查询:可以将其他简单查询组合起来,实现更复杂的搜索逻辑
当我们利用match查询文档时文档结果会根据于搜索词条的关联度打分,返回结果时按照分值进行排列
使用function score query,可以修改文档的相关性算分,根据新的到的算分排序
语法:
#相关性算分
GET /hotel/_search
{
"query": {
"function_score": {
//原始查询条件
"query": {
"match": {
"name": "外滩"
}
},
"functions": [
{
//过滤条件
"filter": {
"term": {
"city": "如家"
}
},
//算分函数
"weight": 10
}
],
//加权模式
"boost_mode": "multiply"
}
}
}
语法解释:
query:原始查询条件,搜索文档并根据相关性打分
functions:
布尔查询是一个或者多个查询子句的组合
需求:搜索名字包含如家,价格不高于400在坐标31.21,121.5周围10km范围的酒店文档
语法:
#布尔查询
GET /hotel/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"name": "如家"
}
}
],
"must_not": [
{
"range": {
"price": {
"gt": 400
}
}
}
],
"filter": [
{
"geo_distance": {
"distance": "10km",
"location": "31.21,121.51"
}
}
]
}
}
}
es支持对搜索结果排序,默认是根据相关度算分来排序,可以排序的字段有:keyword类型、数值类型、地理坐标、日期类型等
通过评分和价格排序:
#通过评分和价格排序
GET /hotel/_search
{
"query": {
"match_all": {}
},
"sort": [
{
"score": {
"order": "desc"
},
"price": {
"order": "asc"
}
}
]
}
当有多个排序条件时会优先执行前面的条件
通过距离排序
#通过距离排序
GET /hotel/_search
{
"query": {
"match_all": {}
},
"sort": [
{
"_geo_distance": {
"location": "31.226215,121.495706",
"order": "asc",
"unit": "km"
}
}
]
}
注意这里的经纬度是纬度在前
es中默认只返回top10的数据,而如果要查询更多数据就需要修改分页参数了
es中通过修改from、size参数来控制返回的分页结果
#分页
GET /hotel/_search
{
"query": {
"match_all": {}
},
//起始记录数
"from": 0,
//获取文档总数
"size": 20
}
语法解释:
from:获取文档的起始位置默认是0(from = size*(page-1))
size:一次获取的文档总数
注意:es能获取到的最大数据为10000
es的分页原理是先查询出分页所需的所有文档(例如from=100,size=10,就会查询出110条数据再返回101-110的数据)当然这在单机状态是没有问题的,在分布式系统中就会出现问题
集群es中的数据是分片存储在不同的es机器上的,假如集群中有100台机器查询数据为from=990,size=10,es就会从不同的es机器上分别查找1000条数据,然后聚合重排序后返回991-1000的数据,这次查询就会查询出100*(990+10)=100000,这10万条数据放进内存重排序时非常消耗cpu和内存甚至造成服务器宕机,所以在业务中应尽量避免使用深度分页(es设定结果集的上限为10000)
针对深度分页,es提供了两种解决方案
search after:分页时需要排序,原理是从上一次的排序值开始,查询下一页数据(官方推荐方式)
scroll:原理将排序数据形成快照,保存在内存(不推荐使用)
es支持给搜索出来的关键字加标签,前端在给相应标签写样式就实现了搜索功能高亮
语法:
#高亮显示
GET /hotel/_search
{
"query": {
"match": {
"all": "如家"
}
},
"highlight": {
//开始标签
"pre_tags": "",
//结束标签
"post_tags": "",
//是否字段匹配,默认情况下搜索字段需要与高亮字段匹配
"require_field_match": "false",
//高亮字段
"fields": {
"name": {},
"brand": {}
}
}
}