[这是我参与11月更文挑战的第21天,活动详情查看:2021最后一次更文挑战]
Elasticsearch 作为一种搜索中间件,也提供了相应的查询语法 DSL(Domain Specific Language)来进行数据查询.由于Elasticsearch提供了REST 风格的API进行查询,所以DSL查询数据也是基于JSON格式的。
什么是DSL
Elasticsearch DSL 是一个高级库,其目的是帮助编写和运行针对 Elasticsearch 的查询。DSL查询可以分为两种:
- 叶查询子句:用于在检索特定字段的特定值,可以单独使用
- 复合查询字句:包含了叶查询以及复合查询
这种设计是把查询视为树结构,如下所示
查询上下文与过滤上下文
在默认情况下,Elasticsearch 按相关性分数对匹配的搜索结果进行排序,相关性分数用于衡量每个文档与查询的匹配程度。分数越高,匹配越高,在返回结果中的排序越靠前。
- 在查询上下文中,查询子句描述了匹配程度。所以除了判断文档是否匹配外,查询子句还会计算
_score元数据字段中的相关性分数。 - 而在过滤上下文中,查询子句只是描述了是否匹配,并不计算分数。Elasticsearch 会自动缓存常用的过滤器,以提高性能。
例如:
GET /_search
{
"query": {
"bool": {
"must": [
{ "match": { "name": "pt" }}
],
"filter": [
{ "range": { "create_date": { "gte": "2021-11-28" }}}
]
}
}
}
高成本的查询
某些类型的查询通常会因其实现方式而执行缓慢,导致一直处于搜索状态,无法与其它节点交互,从而影响集群的稳定性。例如:
- 需要进行线性扫描以识别匹配项的查询
- script
- 初始阶段查询代价过高
- fuzzy(wildcard类型的字段除外)
- regexp(wildcard类型的字段除外)
- prefix(wildcard类型的字段除外或没有启用index_prefixes参数的)
- wildcard(wildcard类型的字段除外)
- range(text和 keyword类型的字段)
- join查询
- 高成本的文本数据查询
- script_score
- percolate
可以通过将search.allow_expensive_queries的值设置为false(默认为true)来阻止此类查询的执行。
复合查询
复合查询可以包装其它复合查询和叶查询,可以:
- 组合结果和分数
- 从查询上下文切换到过滤上下文
复合查询的组成:
- bool
- boosting
- constant_score
- dis_max
- function_score
布尔查询
bool查询用于查询数据是否匹配,由一个或多个布尔字句组成。布尔字句的类型如下:
- must:用作
AND,查询子句必须出现在文档中并且可以增加score数值 - filter:可用作
AND,但是运行在过滤上下文中、忽略分数并且可以被缓存 - should:用作
OR,可以使用minimum_should_match参数设置匹配的最小子句数 - must_not:用作
NOT
例如:
POST book/_search
{
"query": {
"bool": {
"should": [
{
"term": {
"type": {
"value": "大学教材"
}
}
},
{
"term": {
"type": {
"value": "考试认证"
}
}
}
]
}
},
"size": 2,
"aggs": {
"allTYpe": {
"terms": {
"field": "type"
}
}
}
}
Boosting 查询
Boosting查询可以根据字段值改变_score的结果。相关参数如下:
- positive(必选):返回数据集必须与此查询配置
- negative(必选):数据集中匹配的文档,
_score必须乘以negative_boost参数 - negative_boost(必选):浮点数
例如:
POST book/_search?pretty
{
"size": 2,
"query": {
"boosting": {
"positive": {
"term": {
"type": {
"value": "考试认证"
}
}
},
"negative": {
"term": {
"publish": {
"value": "高等教育出版社"
}
}
},
"negative_boost": 0.2
}
},
"_source": ["type","name","publish"]
}
查询结果如下:
{
"took" : 0,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 15,
"relation" : "eq"
},
"max_score" : 0.80781645,
"hits" : [
{
"_index" : "book",
"_type" : "_doc",
"_id" : "35",
"_score" : 0.80781645,
"_source" : {
"publish" : "高等教育出版社",
"name" : "全国计算机等级考试笔试+上机全真模拟:三级网络技术(最新版)",
"type" : "考试认证"
}
},
{
"_index" : "book",
"_type" : "_doc",
"_id" : "38",
"_score" : 0.80781645,
"_ignored" : [
"info.keyword"
],
"_source" : {
"publish" : "高等教育出版社",
"name" : "全国计算机等级考试考点解析例题精解与实战练习:二级C语言程序设计(附光盘)",
"type" : "考试认证"
}
}
]
}
}
固定分数(constant score)
固定分数查询使用了 constant_score参数,具有以下选项:
- filter 用于过滤查询
- boost(可选)设置固定分数,默认为
1.0
例如:
POST book/_search
{
"size": 1,
"from": 6,
"query": {
"constant_score": {
"filter": {
"term": {
"type": "生物科学"
}
},
"boost": 1.2
}
},
"_source": ["type","name","publish"]
}
查询结果如下,可以看到分数固定为1.2:
{
"took" : 0,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 18,
"relation" : "eq"
},
"max_score" : 1.2,
"hits" : [
{
"_index" : "book",
"_type" : "_doc",
"_id" : "222",
"_score" : 1.2,
"_source" : {
"publish" : "高等教育出版社",
"name" : "生态学实验设计与分析(第2版)(中文版)",
"type" : "生物科学"
}
}
]
}
}
查询最匹配字段(dis-query)
在Elasticsearch中,如果返回的文档与多查询子句匹配,dis_max查询会为匹配文档分配最高相关性分数;并为任何其他匹配子查询添加增量,从而避免出现分数相同的情况。相关参数如下:
- queries (必选,查询对象数组)包含一个或多个查询子句,返回的文档需要与这些子句中的一个或多个匹配。
- tie_breaker(必选、浮点数、默认为
0.0)
例如:
POST book/_search
{
"size": 20,
"from": 0,
"_source": ["type","name","publish"],
"explain": true,
"query": {
"dis_max": {
"tie_breaker": 0.7,
"boost": 1.2,
"queries": [
{
"term": {"type": "生物科学"}
}
]
}
}
}
通过函数修改分数
在function_score 查询中,可以为匹配文档调用配置好的函数,从而改变文档的原始分数。
支持以下几个函数:
- script_score:可以包装脚本
- weight:表示权重,用于
乘以分数 - random_score:生成小于1的浮点数;可以设置
seed和field使分数可以重现 - field_value_factor:配置后字段值会影响分数
- decay functions:衰减函数,包括 gauss, linear, exp
例如:
POST book/_search
{
"query": {
"function_score": {
"query": {
"match_all": {}
},
"functions": [
{
"filter": {"term": {
"type": "生物科学"}
},
"random_score": {},
"weight": 1
},
{
"filter": {"term": {
"publish": "农村读物出版社"}
},
"random_score": {},
"weight": 5
}
]
}
},
"size": 20
}