Elasticsearch+Kibana·入门·贰·DSL专题
文章目录
- 1 DSL查询文档
-
- 1.1 DSL查询分类
- 1.2.全文检索查询
-
- 1.2.1 使用场景
- 1.2.2.基本语法:match与multi_match
- 1.2.3 示例:match与multi_match
- 1.3.精准查询
-
- 1.3.1 term查询
- 1.3.2 range查询
- 1.4 地理坐标查询
-
- 1.4.1 矩形范围查询
- 1.4.2 附近查询
- 1.5.复合查询
-
- 1.5.1 相关性算分
-
- 1.5.1.2 算分函数查询
- 1.5.1.3 算分函数运行流程
- 1.5.1.4 算分函数示例
- 1.5.2 布尔查询
-
- 1.5.2.1 语法示例
- 1.5.2.2 示例
1 DSL查询文档
1.1 DSL查询分类
查询类型 | 解释 | 关键字 | 相当于MySQL中 |
---|---|---|---|
查询所有 | 查询出所有数据,一般测试用。 | ① match_all | select * |
全文检索(full text)查询 | 利用分词器对用户输入内容分词,然后去倒排索引库中匹配。 | ①match_query;② multi_match_query | 模糊查询 |
精确查询 | 根据精确词条值查找数据,一般查找keyword、数值、日期、boolean等类型字段 | ① ids;② range;③ term | – |
地理(geo)查询 | 根据经纬度查询 | ① geo_distance;② geo_bounding_box | – |
复合(compound)查询 | 将上述各种查询条件组合起来,合并查询条件。 | ① bool;② function_score | – |
DSL语法:
GET /indexName/_search
{"query": {"查询类型": {"查询条件": "条件值"}}
}
// 查询所有
GET /indexName/_search
{"query": {"match_all": {}}
}
1.2.全文检索查询
1.2.1 使用场景
商城输入框
1.2.2.基本语法:match与multi_match
属性 | 解释 | 备注 |
---|---|---|
match | 单字段查询 | 根据一个字段查询 |
multi_match | 多字段查询,任意一个字段符合条件,只要查到就给你返回 | 根据多个字段查询,参与查询字段越多,查询性能越差,建议使用all字段,copy_to方法优化 |
match查询语法:
GET /indexName/_search
{"query": {"match": {"FIELD": "TEXT"}}
}
mulit_match语法:
GET /indexName/_search
{"query": {"multi_match": {"query": "TEXT","fields": ["FIELD1", " FIELD12"]}}
}
1.2.3 示例:match与multi_match
multi_match 示例:
match 示例:
注意:我们发现上述match、multi_match查询到的结果相同,因为:在Elasticsearch+Kibana·入门·壹中创建索引库时,我们使用到组合字段
all
,已经将brand、name、business值利用copy_to复制到all字段中,因此会出现查询结果相同。
在实际开发者,当查询多个字段时使用copy_to方法,可以减少搜索字段,相较可以提高查询性能。
1.3.精准查询
精准查询一般查找keyword、数值、日期类型字段,所以
不会对搜索条件分词
。
属性 | 解释 |
---|---|
term | 根据词条精确值查询 |
range | 根据值的范围查询 |
1.3.1 term查询
语法:
// term查询
GET /indexName/_search
{"query": {"term": {"FIELD": {"value": "VALUE"}}}
}
term查询:
1.3.2 range查询
语法:
// range查询
GET /indexName/_search
{"query": {"range": {"FIELD": {"gte": 10, // 这里的gte代表大于等于,gt则代表大于"lte": 20 // lte代表小于等于,lt则代表小于}}}
}
range查询示例:
1.4 地理坐标查询
官方参阅文档:https://www.elastic.co/guide/en/elasticsearch/reference/current/geo-queries.html
应用场景:例如查找附近的酒店等。
1.4.1 矩形范围查询
语法:
// 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}}}}
}
1.4.2 附近查询
附近查询(距离查询)geo_distance:以指定点为中心,指定距离为半径的
圆形区域内
所需信息。
语法:
// geo_distance 查询
GET /indexName/_search
{"query": {"geo_distance": {"distance": "15km", // 半径"FIELD": "31.21,121.5" // 圆心}}
}
附近查询示例:
1.5.复合查询
复合(compound)查询:将简单查询组合起来,实现复杂的搜索逻辑。
属性 | 解释 |
---|---|
fuction score | 算分函数查询,通过控制文档相关性算分(权重),控制文档排名 |
bool query | 布尔查询,利用逻辑关系组合多个查询其他查询,实现复杂搜索 |
1.5.1 相关性算分
在elasticsearch中,早期使用的打分算法是TF-IDF算法,公式如下:
注意:TF-IDF算法的
缺陷
,词条频率越高,文档得分(score)越高,词条出现次数对文档影响较大。而BM25则会使单个词条的算分出现上限,分子(词条出现次数过多)趋向于文档中词条总数时,曲线会变平滑,此时相关性算分幅度基本保持不变,使得控制文档排名业务复杂。
5.1版本后,elasticsearch将算法改进为BM25算法,公式如下
1.5.1.2 算分函数查询
算分函数内容 | 解释 |
---|---|
原始查询 | 查询方式可根据需求改变,如:查询品牌中出现万怡字眼的,并中根据下方过滤,得到最终负荷调节的将要设置算分的文档,并得到默认原始算分文档 |
过滤条件 | 查询方式可根据需求改变,得到最终符合条件的将要设置算分文档 |
算分函数 | 与下方boost_mode相结合,再依据原始算分,得到最终算分结果 |
运算模式 | 也就是加权模式,multiply与weight相乘(默认方式) |
1.5.1.3 算分函数运行流程
① 根据原始条件查询文档,得到
原始算分
② 根据过滤条件,过滤文档
③ 得到符合过滤条件的文档,设置权重
,得到函数算分
④ 将此处的加权模式
与上方函数算分
做出计算
,得到最终相关性算分
。
1.5.1.4 算分函数示例
#将上海地区的如家品牌酒店排名靠前
GET /hotel/_search
{"query": {"function_score":{"query": {"match": {"all": "上海"}},"functions": [{"filter": {"term": {"brand": "如家"}},"weight": 100}],"boost_mode": "multiply"}}
}
1.5.2 布尔查询
布尔查询(bool):查询时,在
bool方法体内
,使用一个或多个支持下的组合,每一个字句就是一个子查询,子查询的组合方式:
条件 | 解释 |
---|---|
must | 必须匹配每个子查询,类似“与” |
should | 选择性匹配子查询,类似“或” |
must_not | 必须不匹配,不参与算分,类似“非” |
filter | 必须匹配,不参与算分 |
注意:打分的字段越多,查询的性能也越差。优化方法:
- ①当全文检索时,使用must查询,参与算分
- ②其他过滤条件,采用filter查询,不参与算分
1.5.2.1 语法示例
GET /hotel/_search
{"query": {"bool": {"must": [{"term": {"city": "上海" }}],"should": [{"term": {"brand": "皇冠假日" }},{"term": {"brand": "华美达" }}],"must_not": [{ "range": { "price": { "lte": 500 } }}],"filter": [{ "range": {"score": { "gte": 45 } }}]}}
}
1.5.2.2 示例
需求:搜索名字包含“如家”,价格不高于400,在坐标31.21,121.5周围10km范围内的酒店。
#搜索名字包含“如家”,价格不高于400,在坐标31.21,121.5周围10km范围内的酒店GET /hotel/_search
{"query": {"bool": {"must": [{"match": {//模糊查询,匹配名字中含有如家关键字的酒店吗"name": "如家"}}],"must_not": [{"range": {//子查询"price": {"gt": 400 //非大于400,即小于400的价格}}}],"filter": [ //过滤子查询,得到位置信息内的相关酒店{"geo_distance": {"distance": "10km","location": {"lat": 31.21,"lon": 121.5}}}]}}
}