Elasticsearch学习系列之常用查询表达式Query DSL

Elasticsearch查询模式

一种是像传递URL参数一样去传递查询语句,被称为简单查询

GET /library/books/_search //查询index为library,type为books的全部内容
GET /library/books/_search?q=price:10 //查询index为library,type为books中price等于10的

另一种是DSL语句来进行查询,被称为DSL查询,term和match就属于DSL

查询表达式

查询表达式(Query DSL)是一种非常灵活又富有表现力的查询语言。Elasticsearch 使用它可以以简单的

JSON接口来展现Luncene功能的绝大部分。在你的应用中,你应该用它来编写你的查询语句。它可以使你的

查询语句更灵活、更精确、易读和易调试。

要使用这种查询表达式,只需要将查询语句传递给query参数:

GET /_search
{
    "query": YOUR_QUERY_HERE
}

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

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

查询语句的结构

一个查询语句的典型结构:

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

如果是针对某个字段,那么它的结构如下:

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

举个例子,你可以使用match查询语句来查询tweet字段中包含 elasticsearch 的 tweet:

{
    "match": {
        "tweet": "elasticsearch"
    }
}

完整的查询请求如下:

GET /_search
{
    "query": {
        "match": {
            "tweet": "elasticsearch"
        }
    }
}

合并查询语句

查询语句(Query clauses) 就像一些简单的组合块,这些组合块可以彼此之间合并组成更复杂的查询。这些语句可以是如下形式:

  • 叶子语句(Leaf clauses) (就像 match 语句) 被用于将查询字符串和一个字段(或者多个字段)对比。
  • 复合(Compound) 语句 主要用于 合并其它查询语句。 比如,一个 bool 语句 允许在你需要的时候组合其它语句,无论是 must 匹配、 must_not 匹配还是 should 匹配,同时它可以包含不评分的过滤器(filters):
    {
        "bool": {
            "must":     { "match": { "tweet": "elasticsearch" }},
            "must_not": { "match": { "name":  "mary" }},
            "should":   { "match": { "tweet": "full text" }},
            "filter":   { "range": { "age" : { "gt" : 30 }} }  --包含不含评分的过滤器
        }
    }

一条复合语句可以合并 任何 其它查询语句,包括复合语句,了解这一点是很重要的。这就意味着,复合语句之间可以互相嵌套,可以表达非常复杂的逻辑。

例如,以下查询是为了找出信件正文包含 business opportunity 的星标邮件,或者在收件箱正文包含 business opportunity 的非垃圾邮件:

{
    "bool": {
        "must": { "match":   { "email": "business opportunity" }},
        "should": [
            { "match":       { "starred": true }},
            { "bool": {
                "must":      { "match": { "folder": "inbox" }},
                "must_not":  { "match": { "spam": true }}
            }}
        ],
        "minimum_should_match": 1
    }
}

查询与过滤

(理解查询和上上个例子中filter)

Elasticsearch 使用的查询语言(DSL)拥有一套查询组件,这些组件可以以无限组合的方式进行搭配。这套组件可以在以下两种情况下使用:过滤情况(filtering context)和查询情况(query context)

当使用于 过滤情况  时,查询被设置成一个“不评分”或者“过滤”查询。即,这个查询只是简单的问一个问题:“这篇文档是否匹配?”。回答也是非常的简单,yes 或者 no ,二者必居其一。

  • created 时间是否在 2013 与 2014 这个区间?
  • status 字段是否包含 published 这个单词?
  • lat_lon 字段表示的位置是否在指定点的 10km 范围内?

当使用于 查询情况  时,查询就变成了一个“评分”的查询。和不评分的查询类似,也要去判断这个文档是否匹配,同时它还需要判断这个文档匹配的有 多好(匹配程度如何)。 此查询的典型用法是用于查找以下文档:

  • 查找与 full text search 这个词语最佳匹配的文档
  • 包含 run 这个词,也能匹配 runs 、 running 、 jog 或者 sprint
  • 包含 quick 、 brown 和 fox 这几个词 — 词之间离的越近,文档相关性越高
  • 标有 lucene 、 search 或者 java 标签 — 标签越多,相关性越高

一个评分查询计算每一个文档与此查询的 相关程度,同时将这个相关程度分配给表示相关性的字段 _score并且按照相关性对匹配到的文档进行排序。这种相关性的概念是非常适合全文搜索的情况,因为全文搜索几乎没有完全 “正确” 的答案

最重要的查询

虽然 Elasticsearch 自带了很多的查询,但经常用到的也就那么几个,我们对最重要的几个查询进行简单介绍

term查询

term是代表完全匹配,即不进行分词器分析,文档中必须包含整个搜索的词汇

term查询对于输入的文本不分析,所以它将给定的值进行精确查询。

格式

GET /library/books/_search       #这里是变化的,指定index和type;(比如说index为library,type为books)
{
  "query": {
    "term": {
        "key": "value"              #这里是变化的,比如说查询title等于elasticsearch的内容
      }
    }
}

实例1:查询index为library,type为books重title等于elasticsearch的内容

GET /library/books/_search
{
  "query": {
    "term": {
        "title": "elasticsearch"
    }
  }
}

term查询被用于精确值匹配,这些精确值可能是数字、时间、布尔或者那些not_analyzed的字符串:

{ "term": { "age":    26           }}
{ "term": { "date":   "2014-09-01" }}
{ "term": { "public": true         }}
{ "term": { "tag":    "full_text"  }}

terms查询

terms 查询和 term 查询一样,但它允许你指定多值进行匹配。如果这个字段包含了指定值中的任何一个值,那么这个文档满足条件:

{ "terms": { "tag": [ "search", "full_text", "nosql" ] }}

和 term 查询一样,terms 查询对于输入的文本不分析。它查询那些精确匹配的值(包括在大小写、重音、空格等方面的差异)

match查询

match和term的区别是,match查询的时候,elasticsearch会根据你给定的字段提供合适的分析器,而term查询不会有分析器分析的过程

match查询相当于模糊匹配,只包含其中一部分关键词就行

如果用match下指定了一个确切值,在遇到数字,日期,布尔值或者not_analyzed 的字符串时,它将为你搜索你给定的值。

补充:个人感觉match查询相当于模糊匹配,只包含其中一部分关键词就行,这句话又误,match应该也是精确查询,与term的区别是 term不会有分析器分析的过程。如果想要模糊查询的话,还是用wildcard加通配符。

格式

GET /library/books/_search 
{
    "query":{
        "match":{
            "key":"value"      
        }
    }
}

实例1:过滤出preview字段中包含"elasticsearch"的索引,并且只显示preview和title字段

GET /library/books/_search 
{
    "fields":["preview","title"]
    "query":{
        "match":{
            "preview":"elasticsearch"      
        }
    }
}

如果你在一个全文字段上使用 match 查询,在执行查询前,它将用正确的分析器去分析查询字符串:

{ "match": { "tweet": "About Search" }}

如果在一个精确值的字段上使用它,例如数字、日期、布尔或者一个 not_analyzed 字符串字段,那么它将会精确匹配给定的值:

{ "match": { "age":    26           }}
{ "match": { "date":   "2014-09-01" }}
{ "match": { "public": true         }}
{ "match": { "tag":    "full_text"  }}

match_all查询

查询指定索引下的所有文档

实例1:过滤出index为library,type为books的所有文档

GET /library/books/_search 
{
    "query":{
        "match_all":{}   
        }                                    
}

实例2:通过match_all过滤出所有字段,然后通过partial在过滤出包含preview的字段和排除title,price的字段

GET /library/books/_search 
{
    "partial_fields":{
        "partial":{
            "include":["preview"],         #包含preview字段的文档
            "exclude":["title,price"]    #排除title,price字段
        },
    "query":{
        "match_all":[]
    }
    }
}

match_phrase查询

短语查询,slop定义的是关键词之间隔多少未知单词

格式

GET /library/books/_search 
{
    "query":{
        "match_phrase" :{
            "query":"Elasticsearch,distributed",
            "slop":2                                 #表示Elasticsearch和distributed之间隔多少单词
        }
    }
}

multi_match查询

可以指定多个字段

实例1:查询title和preview这两个字段都包含Elasticsearch关键词的文档

GET /library/books/_search 
{
    "query":{
        "multi_match":{
            "query":"Elasticsearch"
            "fields":["title","preview"]
        }
    }
}

multi_match 查询可以在多个字段上执行相同的 match 查询:

{
    "multi_match": {
        "query":    "full text search",
        "fields":   [ "title", "body" ]
    }
}

range 查询找出那些落在指定区间内的数字或者时间:

{
    "range": {
        "age": {
            "gte":  20,
            "lt":   30
        }
    }
}

被允许的操作符如下:

gt

大于

gte

大于等于

lt

小于

lte

小于等于

exists 查询和 missing 查询

exists 查询和 missing 查询被用于查找那些指定字段中有值 (exists) 或无值 (missing) 的文档。这与SQL中的 IS_NULL (missing) 和 NOT IS_NULL (exists) 在本质上具有共性:

{
    "exists":   {
        "field":    "title"
    }
}

filter过滤查询

查询同时,通过filter条件在不影响打分的情况下筛选出想要的数据

简单的filter查询

实例1:先查询index为store,type为products的全部文档;再过滤price等于20的

GET /store/products/_search
{
  "query": {
    "filtered":{
        "query":{
            "match_all": {}  #先查询index为store,type
        },
        "filter": {
          "term" :{
              "price":20    #这里是条件,price等于20的
          }
        }
    }
  }
}

filter之bool过滤查询

格式

{
"bool":{
    "must"        : [],
    "should"   : [],
    "must_not" : [],
}
}
#must:条件必须满足,相当于sql语句的and
#should:条件可以满足也可以不满足,相当于sql语句的or
#must_not:条件不需要满足,相当于sql语句的not

实例1:查询价格等于20或者productID等于SD1002136的商品,再排除价格等于30的

GET /store/products/_search
{
  "query": {
    "filtered":{
      "filter":{
        "bool":{
          "should": [
            {"term" : {"price" : 20}},
            {"term" : {"productID" : "SD1002136"}}
          ],
          "must_not": {
            "term" :{"price":30}
          }
        }
      
    }
  }
}
}

filter之and,not,or查询

没有bool,也可以直接使用and,or,not

实例1:and用法,查询价格是10元并且productID又是SD1002136的结果

GET /store/products/_search
{
  "query":{
    "filtered":{
      "filter":{
        "and":[
          {
            "term":{
              "price":10
            }
          },
          {
            "term":{
              "productID":"SD1002136"
            }
          }
          ]
      },
      "query":{
        "match_all": {}
      }
    }
  }
  
}

实例2:or用法,查询价格是10元或者productID是SD4535233的商品

GET /store/products/_search
{
  "query":{
    "filtered":{
      "filter":{
        "or":[
          {
            "term":{
              "price":10
            }
          },
          {
            "term":{
              "productID":"SD4535233"
            }
          }
          ]
      },
      "query":{
        "match_all":{}
      }
    }
  }
}

实例3:not用法,查询productID不是SD1002136的商品

GET /store/products/_search
{
  "query":{
    "filtered":{
      "filter":{
        "not":{
          "term":{
            "productID":"SD1002136"
          }
        }
      },
      "query":{
        "match_all": {}
      }
    }
  }
}

filter之range范围查询

格式

GET /store/products/_search
{
    "query":{
        "filtered":{
            "filter":{
                "range":{
                    "key":{
                        "条件" : value1
                        "条件": value2
                    }
                }
            }
        }
    }
}

条件

gt : 大于
lt : 小于
gte : 大于等于
lte :小于等于

实例1:查询price大于等于20小于等于40的结果

GET /store/products/_search
{
    "query":{
        "filtered":{
            "filter":{
                "range":{
                    "price":{
                        "gte" : 20,
                        "lte" : 40
                    }
                }
            }
        }
    }
}

转载于:https://www.cnblogs.com/zhaijunming5/p/6427100.html

https://www.elastic.co/guide/cn/elasticsearch/guide/current/_most_important_queries.html#_exists_%E6%9F%A5%E8%AF%A2%E5%92%8C_missing_%E6%9F%A5%E8%AF%A2

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值