zoukankan      html  css  js  c++  java
  • 结构化查询

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

    空查询
    以最简单的 search API开始,空查询将会返回索引中所有的文档。
    GET /_search

    同字符串查询一样,可以查询一个,多个或 _all索引(indices)或类型(types):
    GET /index_2014*/type1,type2/_search
    现在是:GET /kibana_*/_doc/_search

    可以使用 from 及 size 参数进行分页:

    GET /kibana_sample_data_logs/_doc/_search
    {
      "from": 1,
      "size": 1
    }
    

    任何一种语言(特别是js)的HTTP库都不允许GET请求中携带交互数据。 但是一份规定HTTP语义及内容的RFC中并未规定 GET 请求中允许携带交互数据! 所以,有些HTTP服务允许这种行为,而另一些(特别是缓存代理),则不允许这种行为。

    Elasticsearch的作者们倾向于使用 GET 提交查询请求,因为他们觉得这个词相比 POST 来说,能更好的描述这种行为。 然而,因为携带交互数据的 GET 请求并不被广泛支持,所以 search API同样支持 POST 请求,类似于这样:

    POST /kibana_sample_data_logs/_doc/_search
    {
      "from": 1,
      "size": 1
    }
    

    说明:get和post获得的数据竟然不是同一个数据。。。

    这个原理同样应用于其他携带交互数据的 GET API请求中。

    请求体查询允许我们使用结构化查询Query DSL(Query Domain Specific Language)

    • 结构化查询 Query DSL

    使用结构化查询,你需要传递 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,...
    		}
    	}
    }
    

    完整的查询请求会是这样:

    GET /kibana_sample_data_logs/_search
    {
      "query": {
        "match": {
          "request": "kibana-6.3.2-windows-x86_64.zip"
        }
      },
      "from": 0,
      "size": 3
    }
    

    合并多子句
    查询子句可以合并简单的子句为一个复杂的查询语句.
    复合子句能合并 任意其他查询子句,包括其他的复合子句。 这就意味着复合子句可以相互嵌套,从而实现非常复杂的逻辑。

    GET /kibana_sample_data_logs/_search
    {
      "query": {
        "bool": {
          "must": [
            {"match": {
              "tags": "error"
            }}
          ],
          "should": [
            {"match": {
              "agent": "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)"
            }},
            {
              "bool": {
                "must_not": [
                  {"match": {
                    "machine.os": "win 7"
                  }}
                ]
              }
            }
          ],
          "minimum_should_match": 1
        }
      }
    }
    

    查询与过滤
    可以使用两种结构化语句: 结构化查询(Query DSL)和结构化过滤(Filter DSL)。 查询与过滤语句非常相似,但是它们由于使用目的不同而稍有差异。

    一条过滤语句会询问每个文档的字段值是否包含着特定值,过滤语句的目的就是缩小匹配的文档结果集,所以需要仔细检查过滤条件。
    查询语句会询问每个文档的字段值与特定值的匹配程度如何,典型用法是为了找到文档
    一条查询语句会计算每个文档与查询语句的相关性,会给出一个相关性评分_score,并且按照相关性对匹配到的文档进行排序。 这种评分方式非常适用于一个没有完全配置结果的全文本搜索。

    性能差异
    查询语句不仅要查找相匹配的文档,还需要计算每个文档的相关性,所以一般来说查询语句要比过滤语句更耗时,并且查询结果也不可缓存。

    什么情况下使用
    原则上来说,使用查询语句做全文本搜索或其他需要进行相关性评分的时候,剩下的全部用过滤语句

    • 最重要的查询过滤语句
      term过滤
      term主要用于精确匹配哪些值,比如数字,日期,布尔值或 not_analyzed 的字符串(未经分析的文本数据类型):
    {"term":{"age":26}}
    {"term":{"date":"2014-09-01"}}
    {"term":{"public":true}}
    {"term":{"tag":"full_text"}}
    

    新版本的使用格式要求

    GET /kibana_sample_data_logs/_search
    {
      "query": {
        "term": {
          "timestamp": {
            "value": "2019-12-18 14:33:53"
          }
        }
      }
    }
    

    terms过滤
    terms允许指定多个匹配条件。 如果某个字段指定了多个值,那么文档需要一起去做匹配:

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

    新版本的使用格式要求

    GET /kibana_sample_data_logs/_search
    {
      "query": {
        "terms": {
          "extension": [
            "gz",
            "zip",
            "deb"
          ]
        }
      }
    }
    

    range过滤
    range过滤允许我们按照指定范围查找一批数据:

    GET /kibana_sample_data_ecommerce/_search
    {
      "query": {
        "range": {
          "customer_id": {
            "gte": 20,
            "lte": 30
          }
        }
      }
    }
    

    范围操作符包含:

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

    exists和missing过滤
    exists和missing过滤可以用于查找文档中是否包含指定字段或没有某个字段,类似于SQL语句中的IS_NULL条件

    GET /kibana_sample_data_logs/_search
    {
      "query": {
        "exists": {
          "field": "path"
        }
      }
    }
    
    响应结果
    {
      "took" : 6,
      "timed_out" : false,
      "_shards" : {
        "total" : 1,
        "successful" : 1,
        "skipped" : 0,
        "failed" : 0
      },
      "hits" : {
        "total" : {
          "value" : 0,
          "relation" : "eq"
        },
        "max_score" : null,
        "hits" : [ ]
      }
    }
    
    

    这两个过滤只是针对已经查出一批数据来,但是想区分出某个字段是否存在的时候使用。

    注意:说明,新版本中没有missing了

    bool过滤
    bool 过滤可以用来合并多个过滤条件查询结果的布尔逻辑,它包含一下操作符:

    must  :: 多个查询条件的完全匹配,相当于  and  。
    must_not  :: 多个查询条件的相反匹配,相当于  not  。
    should  :: 至少有一个查询条件匹配, 相当于  or  。
    

    这些参数可以分别继承一个过滤条件或者一个过滤条件的数组:

    GET /kibana_sample_data_logs/_search
    {
      "query": {
        "bool": {
          "must": [
            {"match": {
              "tags": "error"
            }}
          ],
          "should": [
            {"match": {
              "agent": "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)"
            }},
            {
              "bool": {
                "must_not": [
                  {"match": {
                    "machine.os": "win 7"
                  }}
                ]
              }
            }
          ],
          "minimum_should_match": 1
        }
      }
    }
    

    match_all查询
    使用match_all可以查询到所有文档,是没有查询条件下的默认语句。

    {
    	"match_all": {}
    }
    

    此查询常用于合并过滤条件。 比如说你需要检索所有的邮箱,所有的文档相关性都是相同的,所以得到的 _score为1

    match查询
    match 查询是一个标准查询,不管你需要全文本查询还是精确查询基本上都要用到它。
    如果你使用 match 查询一个全文本字段,它会在真正查询之前用分析器先分析 match 一下查询字符
    如果用 match 下指定了一个确切值,在遇到数字,日期,布尔值或者 not_analyzed 的字符串时,它将为你搜索你给定的值

    GET /kibana_sample_data_logs/_search
    {
      "query": {
        "match": {
          "request": "kibana-6.3.2-windows-x86_64.zip"
        }
      },
      "from": 0,
      "size": 3
    }
    

    提示: 做精确匹配搜索时,你最好用过滤语句,因为过滤语句可以缓存数据。

    multi_match查询
    multi_match 查询允许你做 match 查询的基础上同时搜索多个字段:

    GET /kibana_sample_data_logs/_search
    {
      "query": {
        "multi_match": {
          "query": "osx ios",
          "fields": ["machine.os"]
        }
      }
    }
    

    bool查询
    bool过滤可以直接给出是否匹配成功, 而bool查询要计算每一个查询子句的 _score(相关性分值)。

    must  :: 查询指定文档一定要被包含。
    must_not  :: 查询指定文档一定不要被包含。
    should  :: 查询指定文档,有则可以为文档相关性加分。
    

    提示:如果 bool查询下没有must子句,那至少应该有一个should子句。但是如果有must子句,那么没有should子句也可以进行查询。

    查询与过滤条件的合并
    查询语句和过滤语句可以放在各自的上下文中。 在 ElasticSearch API 中我们会看到许多带有query 或 filter 的语句。 这些语句既可以包含单条 query 语句,也可以包含一条 filter 子句。 换句话说,这些语句需要首先创建一个 query 或 filter 的上下文关系。

    复合查询语句可以加入其他查询子句,复合过滤语句也可以加入其他过滤子句。 通常情况下,一条查询语句需要过滤语句的辅助,全文本搜索除外。

    所以说,查询语句可以包含过滤子句,反之亦然。

    带过滤的查询语句
    过滤一条查询语句
    比如说我们有这样一条查询语句:

    {
    	"match": {
    		"email": "business opportunity"
    	}
    }
    

    然后我们想要让这条语句加入 term 过滤,在收信箱中匹配邮件:

    {
    	"term": {
    		"folder": "inbox"
    	}
    }
    

    search API中只能包含 query 语句,所以我们需要用 filtered 来同时包含 "query" 和"filter" 子句:

    {
    	"filtered": {
    		"query": { "match": { "email": "business opportunity" }},
    		"filter": { "term": { "folder": "inbox" }}
    	}
    }
    

    在外层再加入 query 的上下文关系:

    GET /_search
    {
    	"query": {
    		"filtered": {
    			"query": { "match": { "email": "business opportunity" }},
    			"filter": { "term": { "folder": "inbox" }}
    		}
    	}
    }
    

    单条过滤语句
    在 query 上下文中,如果你只需要一条过滤语句,比如在匹配全部邮件的时候,你可以省略query子句:

    GET /_search
    {
    	"query": {
    		"filtered": {
    			"filter": { "term": { "folder": "inbox" }}
    		}
    	}
    }
    

    如果一条查询语句没有指定查询范围,那么它默认使用 match_all 查询,所以上面语句 的完整形式如下:

    GET /_search
    {
    	"query": {
    		"filtered": {
    			"query": { "match_all": {}},
    			"filter": { "term": { "folder": "inbox" }}
    		}
    	}
    }
    

    查询语句中的过滤

    • 验证查询
      validate API 可以验证一条查询语句是否合法
    GET /kibana_sample_data_logs/_validate/query
    {
      "query": {
        "multi_match": {
          "query": "osx ios",
          "fields": ["machine.os"]
        }
      }
    }
    
    查询语句合法的返回结果
    {
      "_shards" : {
        "total" : 1,
        "successful" : 1,
        "failed" : 0
      },
      "valid" : true
    }
    
    查询语句非法的返回结果
    {
      "valid" : false
    }
    
    

    理解错误信息
    想知道语句非法的具体错误信息,需要加上 explain 参数:

    GET /gb/tweet/_validate/query?explain
    {
      "query": {
        "tweet": {
          "match": "really powerful"
        }
      }
    }
    
    具体错误信息
    {
      "valid" : false,
      "error" : "org.elasticsearch.common.ParsingException: no [query] registered for [tweet]"
    }
    
    

    理解查询语句
    如果是合法语句的话,使用 explain 参数可以返回一个带有查询语句的可阅读描述, 可以帮助了解查询语句在ES中是如何执行的:

    GET /kibana_sample_data_logs/_validate/query?explain
    {
      "query": {
        "multi_match": {
          "query": "osx ios",
          "fields": ["machine.os","machine.os.keyword"]
        }
      }
    }
    
    返回结果
    {
      "_shards" : {
        "total" : 1,
        "successful" : 1,
        "failed" : 0
      },
      "valid" : true,
      "explanations" : [
        {
          "index" : "kibana_sample_data_logs",
          "valid" : true,
          "explanation" : "((machine.os:osx machine.os:ios) | machine.os.keyword:osx ios)"
        }
      ]
    }
    
    
  • 相关阅读:
    写一写这几天安卓开发遇到的坑
    安卓环境搭建
    正则表达式
    一段时间的总结
    路飞-登录页面
    路飞-腾讯云短信接口
    路飞-Redis
    路飞-git操作
    路飞-后台xadmin配置
    路飞-后台处理跨域问题
  • 原文地址:https://www.cnblogs.com/sanduzxcvbnm/p/12036237.html
Copyright © 2011-2022 走看看