zoukankan      html  css  js  c++  java
  • 第2部分 Elasticsearch查询-请求体查询、排序

    一、请求体查询

    请求体 search API, 之所以称之为请求体查询(Full-Body Search),因为大部分参数是通过http请求体而非查询字符串来传递的。
    请求体查询:不仅可以处理自身的查询请求,还允许你对结果进行片段强调(高亮)、对所有或部分结果进行聚合分析,同时还可以给出 你是不是想找 的建议,这些建议可以引导使用者快速找到他想要的结果。
    某些特定语言(特别是 JavaScript)的 HTTP 库是不允许 GET 请求带有请求体的,可以用POST代替。

    1、空查询

    空查询,空的请求体会返回所有索引中的所有文档

    GET /_search
    {}
    

    用一个查询字符串,在多个索引库中和多个types中查询:

    GET /index_2014*/type1,type2/_search
    {}
    

    使用 from 和 size 参数分页:

    GET /_search
    {
      "from": 30,
      "size": 10
    }
    

    2、查询表达式(Query DSL)

    使用

    将查询语句传递给query参数

    GET /_search
    {
        "query": YOUR_QUERY_HERE
    }
    

    查询语句结构

    典型结构:

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

    针对某个字段:

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

    例子:

    GET /_search
    {
        "query": {
            "match": {
                "city": "Shaft"
            }
        }
    }
    

    match_all查询

    空查询(empty search),在功能上等价于使用 match_all 查询:

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

    合并查询语句

    叶子语句:用于将查询字符串和一个字段(或者多个字段)对比,match
    复合语句:主要用于合并其它查询语句,bool

    GET /_search
    {
        "query": {
            "bool": {
                "must":{"match":{"state":"KY"}},
                "must_not":{"match":{"city:":"Yettem"}},
                "should":{"match":{"address":"382 Columbia Street"}},
                "filter":   { "range": { "age" : { "gt" : 30 }} }
              }
        }
    }
    

    3、查询与过滤

    过滤
    查询被设置成一个“不评分”或者“过滤”查询。匹配或者不匹配。
    查询
    查询就变成了一个“评分”的查询。一个评分查询计算每一个文档与此查询的相关程度,同时将这个相关程度分配给表示相关性的字段_score,并且按照相关性对匹配到的文档进行排序。
    注意
    "filter" 这个词表示不评分、只过滤情况下的查询。== "filter" 、 "filtering query" 和 "non-scoring query"
    "query" 我们指的是 "scoring query"
    性能差异
    过滤查询(Filtering queries:计算快,经常用不评分查询结果稀少,结果会被缓存到内存中以便快速读取,所以有各种各样的手段来优化查询结果。
    评分查询(scoring queries):计算费力,查询结果并不缓存。

    4、最重要的查询

    match_all查询

    匹配所有文档,默认查询方式。它经常与 filter 结合使用

    { "match_all": {}}
    

    match查询

    标准查询,无论你在任何字段上进行的是全文搜索还是精确查询。
    全文字段使用时,在执行查询前,它将用正确的分析器去分析查询字符串

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

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

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

    multi_match 查询

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

    GET /_search
    {
        "query": {
            "multi_match": {
               "query":    "728",
               "fields":   [ "address", "account_number" ]
             }
        }
    }
    

    解释:查询在address和account_number字段带有728字符串的文档。

    range查询

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

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

    操作符如下:

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

    term查询

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

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

    注意:以上某一行

    terms查询

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

    GET /_search
    {
        "query": {
            "terms": { "age": [39,38,30 ] }
        }
    }
    

    解释:年龄为39或38或30的文档。

    exists查询、missing查询

    用于查找那些指定字段中有值 (exists) 或无值 (missing) 的文档:

    GET /_search
    {
        "query": {
            "exists": {
                "field":    "title"
            }
        }
    }
    

    解释:查询title字段有值的文档

    5、组合多查询

    可用bool查询,它接受以下参数:

    • must:文档 必须 匹配这些条件才能被包含进来。
    • must_not:文档 必须不 匹配这些条件才能被包含进来。
    • should:如果满足这些语句中的任意语句,将增加_score ,否则,无任何影响。它们主要用于修正每个文档的相关性得分。
    • filter:必须 匹配,但它以不评分、过滤模式来进行。这些语句对评分没有贡献,只是根据过滤标准来排除或包含文档。

    bool查询

    查找 title 字段匹配 how to make millions 并且不被标识为 spam 的文档。那些被标识为 starred 或在2014之后的文档,将比另外那些文档拥有更高的排名。如果_两者_都满足,那么它排名将更高:

    {
        "bool": {
            "must":     { "match": { "title": "how to make millions" }},
            "must_not": { "match": { "tag":   "spam" }},
            "should": [
                { "match": { "tag": "starred" }},
                { "range": { "date": { "gte": "2014-01-01" }}}
            ]
        }
    }
    

    增加带过滤器的bool查询

    如果我们不想因为文档的时间而影响得分,可以用 filter 语句来重写前面的例子:

    {
        "bool": {
            "must":     { "match": { "title": "how to make millions" }},
            "must_not": { "match": { "tag":   "spam" }},
            "should": [
                { "match": { "tag": "starred" }}
            ],
            "filter": {
              "range": { "date": { "gte": "2014-01-01" }} ![0f67842b8cc059137a88288e95115a18.png](evernotecid://20C3AB82-3EA7-481C-B3D2-078868D90727/appyinxiangcom/23631184/ENNote/p10?hash=0f67842b8cc059137a88288e95115a18)
              
            }
        }
    }
    

    如果你需要通过多个不同的标准来过滤你的文档,bool查询本身也可以被用做不评分的查询,简单地将它放置到filter语句中并在内部构建布尔逻辑:

    {
        "bool": {
            "must":     { "match": { "title": "how to make millions" }},
            "must_not": { "match": { "tag":   "spam" }},
            "should": [
                { "match": { "tag": "starred" }}
            ],
            "filter": {
              "bool": { ![0f67842b8cc059137a88288e95115a18.png](evernotecid://20C3AB82-3EA7-481C-B3D2-078868D90727/appyinxiangcom/23631184/ENNote/p10?hash=0f67842b8cc059137a88288e95115a18)
              
                  "must": [
                      { "range": { "date": { "gte": "2014-01-01" }}},
                      { "range": { "price": { "lte": 29.99 }}}
                  ],
                  "must_not": [
                      { "term": { "category": "ebooks" }}
                  ]
              }
            }
        }
    }
    
    

    constant_score查询

    可以使用它来取代只有 filter 语句的 bool 查询,性能相同,但是简洁:

    {
        "constant_score":   {
            "filter": {
                "term": { "category": "ebooks" } ![0f67842b8cc059137a88288e95115a18.png](evernotecid://20C3AB82-3EA7-481C-B3D2-078868D90727/appyinxiangcom/23631184/ENNote/p10?hash=0f67842b8cc059137a88288e95115a18)
                
            }
        }
    }
    

    解释:term 查询被放置在 constant_score 中,转成不评分的 filter。这种方式可以用来取代只有 filter 语句的 bool 查询。

    6、验证查询

    validate-query API 可以用来验证查询是否合法:

    GET /bank/address/_validate/query?
    {
       "query": {
          "address" : {
             "match" : "Avenue"
          }
       }
    }
    

    解释不合法原因:

    GET /bank/address/_validate/query?explain
    {
       "query": {
          "address" : {
             "match" : "Avenue"
          }
       }
    }
    

    二、排序与相关性

    1、排序

    在 Elasticsearch 中, 相关性得分 由一个浮点数进行表示,并在搜索结果中通过_score 参数返回, 默认排序是_score 降序。

    使用 constant_score 查询进行替代bool,让所有文档应用一个恒定分数(默认为 1 ),不是0:

    GET /_search
    {
        "query" : {
            "constant_score" : {
                "filter" : {
                    "term" : {
                        "user_id" : 1
                    }
                }
            }
        }
    }
    

    2、按照字段的值排序

    GET /_search
    {
        "query" : {
            "bool" : {
                "filter" : { "term" : { "age" : 40 }}
            }
        },
        "sort": { "balance": { "order": "desc" }}
    }
    

    3、多级排序

    假定我们想要结合使用 date和_score 进行查询,并且匹配的结果首先按照日期排序,然后按照相关性排序:

    GET /_search
    {
        "query" : {
            "bool" : {
                "must":   { "match": { "tweet": "manage text search" }},
                "filter" : { "term" : { "user_id" : 2 }}
            }
        },
        "sort": [
            { "date":   { "order": "desc" }},
            { "_score": { "order": "desc" }}
        ]
    }
    

    Query-string 搜索 也支持自定义排序,可以在查询字符串中使用 sort 参数:

    GET /_search?sort=date:desc&sort=_score&q=search
    

    4、多值字段排序

    情形:一个字段里有多个值,并且这些值没有顺序,应该选择哪个值排序。
    对于数字或日期,你可以将多值字段减为单值,这可以通过使用 min 、 max 、 avg 或是 sum 排序模式 。 例如你可以按照每个 date 字段中的最早日期进行排序,通过以下方法:

    "sort": {
        "dates": {
            "order": "asc",
            "mode":  "min"
        }
    }
    

    5、字符串排序与多字段

    一个简单的方法是用两种方式对同一个字符串进行索引,这将在文档中包括两个字段: analyzed 用于搜索, not_analyzed 用于排序。

    为一个多字段映射如:

    "tweet": { ![0f67842b8cc059137a88288e95115a18.png](evernotecid://20C3AB82-3EA7-481C-B3D2-078868D90727/appyinxiangcom/23631184/ENNote/p10?hash=0f67842b8cc059137a88288e95115a18)
    
        "type":     "string",
        "analyzer": "english",
        "fields": {
            "raw": {        
                "type":  "string",
                "index": "not_analyzed"
            }
        }
    }
    
    
    • tweet 主字段与之前的一样: 是一个 analyzed 全文字段。
    • 新的 tweet.raw 子字段是 not_analyzed.

    现在,使用 tweet 字段用于搜索,tweet.raw 字段用于排序:

    GET /_search
    {
        "query": {
            "match": {
                "tweet": "elasticsearch"
            }
        },
        "sort": "tweet.raw"
    }
    

    注意:以全文 analyzed 字段排序会消耗大量的内存

  • 相关阅读:
    POJ 3261 Milk Patterns (求可重叠的k次最长重复子串)
    UVaLive 5031 Graph and Queries (Treap)
    Uva 11996 Jewel Magic (Splay)
    HYSBZ
    POJ 3580 SuperMemo (Splay 区间更新、翻转、循环右移,插入,删除,查询)
    HDU 1890 Robotic Sort (Splay 区间翻转)
    【转】ACM中java的使用
    HDU 4267 A Simple Problem with Integers (树状数组)
    POJ 1195 Mobile phones (二维树状数组)
    HDU 4417 Super Mario (树状数组/线段树)
  • 原文地址:https://www.cnblogs.com/yangjianan/p/10525925.html
Copyright © 2011-2022 走看看