elasticsearch(5) 请求体搜索

上一篇提到的轻量搜索非常简单便捷,但是通过请求体查询可以更充分的利用查询的强大功能。因为_search api中大部分参数是通过HTTP请求体而非查询字符串来传递的。

一 空查询

对于空查询来说,最简单的方式就是传入一个空的请求体,获取所有文档(默认返回前10个完整文档内容)

GET 127.0.0.1:9200/_search

{}

你也可以使用from 和 size参数

GET 127.0.0.1:9200/_search
{
      "from":10,
      "size":5
}    

这样的方式来查询第11条到15条的文档

  • 大家可能会好奇,这明明是一个GET请求方式,为何可以有请求体。事实上这个RFC文档 RFC 7231— 一个专门负责处理 HTTP 语义和内容的文档 — 并没有规定一个带有请求体的 GET 请求应该如何处理。结果是,一些 HTTP 服务器允许这样子,而有一些 — 特别是一些用于缓存和代理的服务器则不允许。

为了避免这样的情况,ES也支持通过POST请求来进行查询

POST 127.0.0.1:9200/_search
{
      "from":10,
      "size":5
}    

二 查询结构

查询表达式(Query DSL)是一种非常灵活又富有表现力的 查询语言。 Elasticsearch 使用它可以以简单的 JSON 接口来展现 Lucene 功能的绝大部分。在你的应用中,你应该用它来编写你的查询语句。它可以使你的查询语句更灵活、更精确、易读和易调试。

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

  •  典型的查询语句结构
{
    QUERY_NAME: {
        ARGUMENT: VALUE,
        ARGUMENT: VALUE,...
    }
}

例如

{
    "query": {
        "match": {
            "like": "sport"
        }
    }
}

查询like字段包含sport的文档

  • 合并查询语句

查询语句就行一个组合块,这些组合块可以合并组成更加复杂的查询逻辑

合并查询语句里分为两种类型

1、叶子语句

即类似上述的match语句,可以被用来查询一个或多个字段的文档

2、复合语句

用于合并其他查询语句,可以通过一个bool语句组合其他语句,例如must匹配、must_not匹配,should匹配,或者filters过滤器

示例

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

找出信件正文包含 business opportunity 的星标邮件,或者在收件箱正文包含business opportunity 的非垃圾邮件

三 查询与过滤

查询组件的使用可以分为两种情况,查询情况和过滤情况,这两种情况是有区别的

  • 对于过滤情况来说,ES只是简单的过滤查询,对于文档是不会进行评分的,即文档要么匹配,要么就是不匹配,并没有介于其中的中间状态。

这种方式比较适用于确定的判断,例如created介于2017和2018之间,status等于有效等等

  • 对于查询情况来说,查询就有了评分,不但需要判断文档是否匹配,还需要判断这个文档匹配的多好。

这种情况比较适用于全文搜索,因为全文搜索几乎没有完全正确的答案

一般情况下,由于查询情况需要评分,所以它的效率是没有过滤情况来的好的。通常使用 查询(query)语句来进行全文 搜索或者其它任何需要影响相关性得分的搜索。除此以外的情况都使用过滤(filters)。

  • 实际上从ES2.0开始,过滤情况已经基本被排除了,因为查询拥有了不评分的能力。

四 查询方法

  • match_all

match_all查询简单的匹配所有文档,在没有指定查询方式时,它是默认的查询,它经常与 filter 结合使用。由于所有文档被认为具有相同的相关性,所以文档的_score都为1

{
    "query": {
        "match_all": {}
    }
}
  • match

无论你在任何字段上进行的是全文搜索还是精确查询,match 查询是你可用的标准查询。如果是在全文字段上match,那么就会使用正确的分析器取分析查询字符串,如果是在精确值例如整型,时间等,那么就会精确匹配它。这部分内容会在后面的映射分析部分讲到。

{
    "query": {
        "match": {
            "like": "sport"
        }
    }
}
  • multi_match

multi_match查询可以在多个字段上执行相同的match, query属性里是查询的条件,fields属性对应的是多个字段。

{
    "query": {
        "multi_match": {
            "query": "sport",
            "fields":["like","career"]
        }
    }
}
  • range查询

range查询可以找出落在指定区间内的数字或者时间,被允许的操作符有

gt:大于

gte:大于等于

lt:小于

lte:小于等于

{
    "query": {
        "range": {
            "age": {
                "gte": 20,
                "lt": 30
            }
        }
    }
}
  • term查询

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

{ "term": { "age":    26           }}
  • terms查询

和term一样,但terms允许指定多值进行匹配,若包含任一值,文档则匹配。匹配的多值通过[ ] 来列出

{ "terms": { "tag": [ "search", "full_text", "nosql" ] }}
  • exists查询

查询指定字段有值,NOT NULL。field:指定字段

{
    "exists":   {
        "field":    "title"
    }
}
  • missing查询

和exists相反,查询指定字段无值 NULL.

五 组合多查询

可以通过bool查询来合并组合多查询,bool查询接受一下参数

  • must

文档必须匹配这些条件才能被包含

  • must_not

文档必须不匹配这些条件才能被包含

  • should

如果满足这些语句中的任意语句,将会增加_score,否则无任何影响,它主要用于修正每个文档的相关性得分

  • filter

必须匹配,但它以不评分、过滤模式来进行。这些语句对评分没有贡献,只是根据过滤标准来排除或包含文档。所有查询包括bool查询本身都可以放置在filter语句中,使其本身不做评分。

  • 如果没有must语句,那么至少需要能够匹配其中的一条 should 语句。但,如果存在至少一条 must 语句,则对 should 语句的匹配没有要求。

六 验证查询

可以使用_validate/query来验证查询是否合法

GET /test/test/_validate/query
{
   "query": {
      "like" : {
         "match" : "sport"
      }
   }
}

响应

{
  "valid" :         false,
  "_shards" : {
    "total" :       10,
    "successful" :  10,
    "failed" :      0
  }
}

这告诉我们这是非法的查询,这时我们可以使用explain来查询原因

GET /gb/tweet/_validate/query?explain 
{
   "query": {
      "tweet" : {
         "match" : "really powerful"
      }
   }
}

响应

{
  "valid" :     false,
  "_shards" :   { ... },
  "explanations" : [ {
    "index" :   "gb",
    "valid" :   false,
    "error" :   "org.elasticsearch.index.query.QueryParsingException:
                 [gb] No query registered for [tweet]"
  } ]
}

这告诉我们query中没有注册的tweet,应该把match和tweet调换位置

猜你喜欢

转载自www.cnblogs.com/wuzhe1991/p/9981331.html