Elasticsearch Query DSL

DSL 即 Domain Specific Language,是ES的JSON结构查询语法。

这个查询语法总体上包含2个部分:

叶子查询:对字段进行match、term、range等条件匹配

复合查询:复合查询包装其他叶子查询或复合查询

 

另外要注意在ES中有些查询的开销是比较大的:

可以通过将 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开始的复合查询,包含以下子查询

must

必须匹配,对得分起作用

filter

必须匹配,起到过滤作用,属于 filter context ,对得分不起作用,过滤能起到缓存作用

should

表示可以匹配,对得分起作用。它有一个minimum_should_match属性,表示至少应该匹配的数量,当bool中没有must或filter时,minimum_should_match的默认值是1,否则是0

must_not

必须不匹配,它也属于 filter context 中的,因此对得分不起作用,也进行缓存

关于minimum_should_match的取值,参考如下

TypeExampleDescription

Integer

3

表示至少匹配3项

Negative integer

-2

表示总共的匹配项的数量 减去 2,例如10-2=7

Percentage

75%

表示总共的匹配项的数量的 75%,向下舍去并使用最小值(总共的匹配项的数量 和 向下舍去后的值),例如10*75%=7,1*75%=1

Negative percentage

-25%

表示总共的匹配项的数量 减去 25%,百分比的值向下舍去,然后从总数中减去以确定最小值,例如10-10*25%=8,1-1*25%=1

Combination

3<90%

左边是正整数L,中间是<符号,右边是正的百分比R。

设 N=总共的匹配项的数量,如果N小于等于L,则要匹配的数量是L,否则相当于 R,例如N是3时,结果=3,N是10时,结果=9

Multiple combinations

2<-25% 9<-3

复合条件,中间用空格。在本例中:如果有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"
        }
      }
    }
  }
}

{
    "took": 4,
    "timed_out": false,
    "_shards": {
        "total": 1,
        "successful": 1,
        "skipped": 0,
        "failed": 0
    },
    "hits": {
        "total": {
            "value": 1,
            "relation": "eq"
        },
        "max_score": 1.3862942,
        "hits": [
            {
                "_index": "my-index-000001",
                "_type": "_doc",
                "_id": "m1j9yXwBsMHt3M__NQSV",
                "_score": 1.3862942,
                "_source": {
                    "name.first": "shay",
                    "name.last": "banon"
                },
                "matched_queries": [
                    "last",
                    "test",
                    "first"
                ]
            }
        ]
    }
}

 

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,最终的评分的流程是

  1. 取得原得分
  2. 原得分 乘以 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

 

posted on 2021-10-29 10:52  icodegarden  阅读(70)  评论(0编辑  收藏  举报