Elasticsearch 结构化查询

请求体查询

  • 简单查询语句(lite)是一种有效的命令行adhoc 查询。但是,如果你想要善用搜索,你必须使用请求体查询(request body search)API。之所以这么称呼,是因为大多数的参数以JSON格式所容纳而非查询字符串。
  • 请求体查询(下文简称查询),并不仅仅用来处理查询,而且还可以高亮返回结果中的片段,并且给出帮助你的用户找寻最好结果的相关数据建议。

空查询

  • 我们以最简单的 search API开始,空查询将会返回索引中所有的文档。
    GET /_search
    {} <1>
    
  • <1> 这是一个空查询数据。
  • 同字符串查询一样,你可以查询一个,多个或_all索引(indices)或类型(types):
    GET /index_2014*/type1,type2/_search
    {}
    
  • 你可以使用fromsize参数进行分页:
    GET /_search
    {
      "from": 30,
      "size": 10
    }
    

携带内容的GET请求?

  • 任何一种语言(特别是js)的HTTP库都不允许GET请求中携带交互数据。 事实上,有些用户很惊讶GET请求中居然会允许携带交互数据。
  • 真实情况是,[http://tools.ietf.org/html/rfc7231#page-24RFC 7231], 一份规定HTTP语义及内容的RFC中并未规定GET请求中允许携带交互数据! 所以,有些HTTP服务允许这种行为,而另一些(特别是缓存代理),则不允许这种行为。
  • Elasticsearch的作者们倾向于使用GET提交查询请求,因为他们觉得这个词相比POST来说,能更好的描述这种行为。 然而,因为携带交互数据的GET请求并不被广泛支持,所以searchAPI同样支持POST请求,类似于这样:
    POST /_search
    {
      "from": 30,
      "size": 10
    }
    
  • 这个原理同样应用于其他携带交互数据的GETAPI请求中。

我们将在后续的章节中讨论聚合查询,但是现在我们把关注点仅放在查询语义上。相对于神秘的查询字符串方法,请求体查询允许我们使用结构化查询Query DSL(Query Domain Specific Language)

结构化查询 Query DSL

结构化查询是一种灵活的,多表现形式的查询语言。 Elasticsearch在一个简单的JSON接口中用结构化查询来展现Lucene绝大多数能力。 你应当在你的产品中采用这种方式进行查询。它使得你的查询更加灵活,精准,易于阅读并且易于debug。

  • 使用结构化查询,你需要传递query参数:
    GET /_search
    {
        "query": YOUR_QUERY_HERE
    }
    
  • 空查询 - {} - 在功能上等同于使用match_all查询子句,正如其名字一样,匹配所有的文档:
    GET /_search
    {
        "query": {
            "match_all": {}
        }
    }
    

查询子句

  • 一个查询子句一般使用这种结构:
    {
        QUERY_NAME: {
            ARGUMENT: VALUE,
            ARGUMENT: VALUE,...
        }
    }
    
  • 或指向一个指定的字段:
    {
        QUERY_NAME: {
            FIELD_NAME: {
                ARGUMENT: VALUE,
                ARGUMENT: VALUE,...
            }
        }
    }
    
  • 例如,你可以使用match查询子句用来找寻在tweet字段中找寻包含elasticsearch的成员:
    {
        "match": {
            "tweet": "elasticsearch"
        }
    }
    
  • 完整的查询请求会是这样:
    GET /_search
    {
        "query": {
            "match": {
                "tweet": "elasticsearch"
            }
        }
    }
    

合并多子句

查询子句就像是搭积木一样,可以合并简单的子句为一个复杂的查询语句,比如:

  • 叶子子句(leaf clauses )(比如match子句)用以在将查询字符串与一个字段(或多字段)进行比较
  • 复合子句(compound )用以合并其他的子句。例如,bool子句允许你合并其他的合法子句,mustmust_not或者should,如果可能的话:
    {
        "bool": {
            "must":     { "match": { "tweet": "elasticsearch" }},
            "must_not": { "match": { "name":  "mary" }},
            "should":   { "match": { "tweet": "full text" }}
        }
    }
    
  • 复合子句能合并 任意 其他查询子句,包括其他的复合子句。 这就意味着复合子句可以相互嵌套,从而实现非常复杂的逻辑。
  • 以下实例查询的是邮件正文中含有“business opportunity”字样的星标邮件或收件箱中正文中含有“business opportunity”字样的非垃圾邮件:
    {
        "bool": {
            "must": { "match":      { "email": "business opportunity" }},
            "should": [
                 { "match":         { "starred": true }},
                 { "bool": {
                       "must":      { "folder": "inbox" }},
                       "must_not":  { "spam": true }}
                 }}
            ],
            "minimum_should_match": 1
        }
    }
    
  • 不用担心这个例子的细节,我们将在后面详细解释它。 重点是复合子句可以合并多种子句为一个单一的查询,无论是叶子子句还是其他的复合子句。