• 结构化查询


    • 请求体查询
      简单查询语句(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)"
        }
      ]
    }
    
    
  • 相关阅读:
    day 66 ORM django 简介
    day 65 HTTP协议 Web框架的原理 服务器程序和应用程序
    jQuery的事件绑定和解绑 事件委托 轮播实现 jQuery的ajax jQuery补充
    background 超链接导航栏案例 定位
    继承性和层叠性 权重 盒模型 padding(内边距) border(边框) margin 标准文档流 块级元素和行内元素
    属性选择器 伪类选择器 伪元素选择器 浮动
    css的导入方式 基础选择器 高级选择器
    03-body标签中相关标签
    Java使用内存映射实现大文件的上传
    正则表达式
  • 原文地址:https://www.cnblogs.com/sanduzxcvbnm/p/12036237.html
Copyright © 2020-2023  润新知