Elasticsearch Query DSL
DSL 即 Domain Specific Language,是ES的JSON结构查询语法。
这个查询语法总体上包含2个部分:
叶子查询:对字段进行match、term、range等条件匹配
复合查询:复合查询包装其他叶子查询或复合查询
另外要注意在ES中有些查询的开销是比较大的:
-
需要进行线性扫描的查询(类似全表扫描):
-
具有高预付成本的查询:
fuzzy
queries模糊查询 (wildcard
除外)regexp
queries正则查询
(wildcard
除外)prefix
queries前缀查询 (wildcard
除外 or 没有index_prefixes
的除外)wildcard
queries通配符查询 (wildcard
除外)range
queries范围查询 ontext
andkeyword
fields
- Joining queries
- deprecated geo-shapes对不推荐的地理形状的查询
-
每个文档的成本可能很高的查询:
可以通过将 search.allow_expensive_querys 设置为false(默认为true)的值来阻止执行此类查询。
Query and filter context 上下文
关于相关性得分:
默认情况下,ES根据相关性得分对匹配的搜索结果进行排序,相关性得分衡量每个文档与查询的匹配程度。
相关性分数是一个正浮点数,在_score元数据字段中返回。分数越高,文档的匹配程度就越高。
Query context:除了决定文档是否匹配外,还计算_score元数据字段中的相关性分数。
filter context:这种匹配是对 是或否 的匹配,因此不会计算得分。经常使用的过滤器将由Elasticsearch自动缓存,以提高性能。
看下面这个例子,
query表示查询的开始
bool和两个match子句用于query context,用于对每个文档的匹配程度进行评分
filter用于filter context,它们将过滤掉不匹配的文档,但不会影响匹配文档的分数。
GET /_search
{
"query": {
"bool": {
"must": [
{ "match": { "title": "Search" }},
{ "match": { "content": "Elasticsearch" }}
],
"filter": [
{ "term": { "status": "published" }},
{ "range": { "publish_date": { "gte": "2015-01-01" }}}
]
}
}
}
Compound queries 复合查询
bool
query 以bool开始的复合查询,包含以下子查询
|
必须匹配,对得分起作用 |
|
必须匹配,起到过滤作用,属于 filter context ,对得分不起作用,过滤能起到缓存作用 |
|
表示可以匹配,对得分起作用。它有一个minimum_should_match属性,表示至少应该匹配的数量,当bool中没有must或filter时,minimum_should_match的默认值是1,否则是0 |
|
必须不匹配,它也属于 filter context 中的,因此对得分不起作用,也进行缓存 |
关于minimum_should_match的取值,参考如下
Type | Example | Description |
---|---|---|
Integer |
|
表示至少匹配3项 |
Negative integer |
|
表示总共的匹配项的数量 减去 2,例如10-2=7 |
Percentage |
|
表示总共的匹配项的数量的 75%,向下舍去并使用最小值(总共的匹配项的数量 和 向下舍去后的值),例如10*75%=7,1*75%=1 |
Negative percentage |
|
表示总共的匹配项的数量 减去 25%,百分比的值向下舍去,然后从总数中减去以确定最小值,例如10-10*25%=8,1-1*25%=1 |
Combination |
|
左边是正整数L,中间是<符号,右边是正的百分比R。 设 N=总共的匹配项的数量,如果N小于等于L,则要匹配的数量是L,否则相当于 R,例如N是3时,结果=3,N是10时,结果=9 |
Multiple combinations |
|
复合条件,中间用空格。在本例中:如果有1或2个项,则结果=2;如果有3-9个项,则结果=-25%;如果有9个以上的项,则结果=-3 |
Named queries 允许在query时使用_name,在返回的结果中将包含matched_queries字段,表示哪些条件匹配到了
GET /_search { "query": { "bool": { "should": [ { "match": { "name.first": { "query": "shay", "_name": "first" } } }, { "match": { "name.last": { "query": "banon", "_name": "last" } } } ], "filter": { "terms": { "name.last": [ "banon", "kimchy" ], "_name": "test" } } } } }
boosting
query 干预得分的查询
GET /_search
{
"query": {
"boosting": {
"positive": {
"term": {
"text": "apple"
}
},
"negative": {
"term": {
"text": "pie tart fruit crumble tree"
}
},
"negative_boost": 0.5
}
}
}
必须要携带以下参数
positive 是期望的正向匹配
negative 影响得分的反向匹配,如果返回的文档匹配positive和negative,最终的评分的流程是
- 取得原得分
- 原得分 乘以
negative_boost
.
negative_boost 0-1.0之间,起到反向评分系数的作用
constant_score
query 常量得分,得分等于boost
的值
GET /_search
{
"query": {
"constant_score": {
"filter": {
"term": { "user.id": "kimchy" }
},
"boost": 1.2
}
}
}
参数filter、boost都是必须的。
dis_max
query 逻辑或,返回与一个或多个条件匹配的文档,匹配的越多分值越大。
GET /_search
{
"query": {
"dis_max": {
"queries": [
{ "term": { "title": "Quick pets" } },
{ "term": { "body": "Quick pets" } }
],
"tie_breaker": 0.7
}
}
}
queries 必填,必须匹配1个以上。
tie_breaker 可选的float,0.0-1.0,默认0.0。
如果一个文档匹配多个子句,dis_max查询的得分规则:
从得分最高的匹配从句中获取相关性得分。
将任何其他匹配子句的分数乘以tie_breaker 。
将最高分数与乘以的分数相加。
如果tie_breaker 值大于0.0,则所有匹配的子句都将计算在内,但得分最高的子句最为重要。
function_score
query 函数式得分
允许修改查询检索到的文档的分数。例如,如果一个score函数在计算上很昂贵,并且在一组过滤过的文档上计算分数就足够了,那么这将非常有用。
要使用function_score,用户必须定义一个query和一个或多个functions,为查询返回的每个文档计算新的分数。
function_score与一个function一起使用时:
GET /_search
{
"query": {
"function_score": {
"query": { "match_all": {} },
"boost": "5",
"random_score": {},
"boost_mode": "multiply"
}
}
}
与多个fucntion使用时:
GET /_search
{
"query": {
"function_score": {
"query": { "match_all": {} },
"boost": "5",
"functions": [
{
"filter": { "match": { "test": "bar" } },
"random_score": {},
"weight": 23
},
{
"filter": { "match": { "test": "cat" } },
"weight": 42
}
],
"max_boost": 42,
"score_mode": "max",
"boost_mode": "multiply",
"min_score": 42
}
}
}
在这种情况下,可以选择仅当文档与给定的筛选查询匹配时才应用该function