Elasticsearch学习笔记之查询表达式


一、前言:

Elasticsearch的查询分为两种一种是通过设置get请求的参数实现,一种是利用post传递查询表达式。
查询表达式(Query DSL)是一种非常灵活又富有表现力的查询语言。 Elasticsearch使用简单的 JSON 接口来展现 Lucene 功能的绝大部分。在你的应用中,你应该用它来编写你的查询语句。它可以使你的查询语句更灵活、更精确、易读和易调试。

二、查询语句的结构

查询表达式,只需将查询语句传递给 query 参数:

POST /_search
{
    "query": YOUR_QUERY_HERE
}

ps:查询表达式需要使用post方法请求_search路径。或者使用/{index}/{type}/_search。可以对应索引下对应类型进行查询。

2.1 查询:

2.1.1 空查询(empty search)

在功能上等价于使用 match_all 查询, 正如其名字一样,匹配所有文档:
空查询

{}

match_all查询

POST /_search
{
    "query": {
        "match_all": {}
    }
}

空查询可以指定from和size进行分页查询

POST /_search
{
  "from": 30,
  "size": 10
}

2.1.2 查询的典型结构:

{
    QUERY_NAME: {
        ARGUMENT: VALUE,
        ARGUMENT: VALUE,...
    }
}

完整结构如下:

{
    "query":{
     <   "bool":{ >
            "Query_Action":{
                "Field_Name":{
                    "Argument":"Value"
                }
            },
            "filter" : {
                "Query_Action":{
                    "Field_Name":{
                     "Argument":"Value"
                    }
                }
        }
   < } >
}

Query_Action: 我归类的方式有:

  1. 布尔查询:must,must_not,should等 类似SQL的and,or,! 等
  2. 匹配查询: match multi_match等 类似SQL的like
  3. 范围查询: range 类似SQL的大于,小于,等于等
  4. term查询: term 类似SQL的 “=”
  5. 正则查询: regex 这个就不说了
  6. exists和missing查询: 类似于SQL is null,is not null

查询语法总结:

  1. 最外层必须是query对象
  2. 复合查询条件要包含在bool对象中
  3. 过滤器里面也是各种查询动作(不知道filter里面能不能放bool查询)
  4. 布尔查询可以是数组结构,包含多个条件。

2.1.3 布尔查询

must查询

must查询是必要条件,无论must和should,must_not如何搭配必须满足must查询的条件。

POST /my_index/my_type/_search
{
  "query": {
    "bool": {
      "must":     { "match": { "title": "quick" }}
    }
  }
}
must_not查询

must_not查询不参与匹配,只是把匹配结果中符合条件的去除掉。

POST /my_index/my_type/_search
{
  "query": {
    "bool": {
      "must":     { "match": { "title": "quick" }},
      "must_not": { "match": { "title": "lazy"  }}
    }
  }
}
should查询

should查询不影响匹配结果,只是当符合条件时,文档会被认为更相关。除非是查询语句中只包含should条件,那么必须满足最少一个should条件。可以通过minimum_should_match属性来控制满足条件的个数。

POST /my_index/my_type/_search
{
  "query": {
    "bool": {
      "should": [
        { "match": { "title": "brown" }},
        { "match": { "title": "fox"   }},
        { "match": { "title": "dog"   }}
      ],
      "minimum_should_match": 2 
    }
  }
}

2.1.4匹配查询

match查询:

match查询接受文本/数字/日期类型数据,然后进行分析后构建一次查询。

POST /_search
{
    "query": {
        "match" : {
            "message" : "this is a test"
        }
    }
}

match查询本质上也是一种布尔查询,含义是查询文本被分析后构建成了一个布尔查询。operator属性可以用来控制构建的布尔查询语句的逻辑关系(or,and)。如果将operator设置为and,但是又想获得一些不完全匹配的结果,可以设置minimum_should_match属性。

POST /_search
{
    "query": {
        "match" : {
            "message" : {
                "query" : "this is a test",
                "operator" : "and"
            }
        }
    }
}
match_phrase查询

match_phrase查询对query进行分析(分词)后,创建一个短语查询。 match_phrase查询要求查询的term都存在,同时按照输入的顺序排列。  默认情况下,term之间必需是紧挨着才能被查询到。但是我们通过设置slop属性控制term之间的间隔。
ps: 中文utf-8编码,一个字算两个单位

POST /_search
{
    "query": {
        "match_phrase" : {
            "message" : {
            	"query":  "this is a test",
        		"slop" : 4
            }	
        }
    }
}
match_phrase_prefix查询

The match_phrase_prefix is the same as match_phrase, except that it allows for prefix matches on the last term in the text.
match_phrase_prefix基本上同match_phrase相同,除了它允许匹配最后一个term的前缀。不过这种匹配在中文语境下就和match_phrase区别不大了。

multi_match查询

就是一个query可以在多个域上进行查询。

POST /_search
{
  "query": {
    "multi_match" : {
      "query":    "this is a test", 
      "fields": [ "subject", "message" ] 
    }
  }
}

还可以使用通配符

POST /_search
{
  "query": {
    "multi_match" : {
      "query":    "Will Smith",
      "fields": [ "title", "*_name" ] 
    }
  }
}

multi_match如果只是支持在多个域上面查询,那我们可以直接使用match然后在多个域上查就好了嘛。multi_match不一样的是支持上述的所有查询类型,如下表。

查询类型作用best_fields默认类型,在所有域上查询文档。但是使用最佳匹配的域作为_score。most_fields在所有域上查询文档,和best_fields不同的是最后的_score是所有域查询结果的平均分。cross_fields很复杂,简单说就是一个查询在被分词后,对分词的结果在多个域上查询,每个词只要在某个域上存在就可以。也就是跨域phrase在每个域上进行phrase查询,然后选择结果最高的_score作为这个查询结果的_scorephrase_prefix在每个域上进行phrase_prefix查询,然后最后查询结果的_score是所有域查询结果的平均分。

不匹配所有查询:

匹配所有查询的反转,不匹配所有文档,虽然我暂时没想到这个可以用来干什么。

GET /_search
{
    "query": {
        "match_none": {}
    }
}

2.1.5 term查询

和匹配查询不同的就是,term查询对每个域都需要是完全相同的匹配。

term查询
POST _search
{
  "query": {
    "term" : { "user" : "Kimchy" } 
  }
}

上面的查询结果是在user域上是Kimchy的所有文档。

terms查询

匹配多个term查询结果

POST _search
{
    "query": {
        "terms" : { "user" : ["kimchy", "elasticsearch"]}
    }
}

查询结果是user域上为kimchy或者elasticsearch的文档。

2.1.6 range查询

range查询要以range对象开始,接受以下参数:

参数含义gte大于等于gt大于lte小于等于lt小于

ps:只有string,number,date三种数据类型可以进行range查询

POST _search
{
    "query": {
        "range" : {
            "age" : {
                "gte" : 10,
                "lte" : 20,
                "boost" : 2.0
            }
        }
    }
}

2.1.7 exists查询和missing查询

POST /_search
{
    "query": {
        "exists" : { "field" : "user" }
    }
}

exists查询用来判断某个域是否有值,具体来说:

{ "user": "jane" }
{ "user": "" } 
{ "user": "-" } 
{ "user": ["jane"] }
{ "user": ["jane", null ] } 

以上都判断有值

{ "user": null }
{ "user": [] } 
{ "user": [null] } 
{ "foo":  "bar" } 

以上都默认无值

POST /_search
{
    "query": {
        "bool": {
            "must_not": {
                "exists": {
                    "field": "user"
                }
            }
        }
    }
}

missing查询就是exists查询的否定了~

三、总结:

Elasticsearch的查询表达式是非常重要必须要掌握的知识,但是总的来说比较复杂,这篇笔记把主要的部分归纳总结。后面会逐渐完善更多的知识。

Reference:

  1. https://www.cnblogs.com/sunfie/p/6653778.html
  2. Elasticsearch官方文档6.4版本 https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html