美文网首页
Elasticsearch学习笔记(16) - Query &

Elasticsearch学习笔记(16) - Query &

作者: juconcurrent | 来源:发表于2019-08-28 20:14 被阅读0次

    前言

    Elasticsearch有Query和Filter两种不同的Context。

    1. Query Context,会进行相关性算分
    2. Filter Context,不会进行相关性算分,这种方式可利用缓存来提高检索的速度和性能。

    Bool查询

    Bool查询是一种复合查询,是一个或多个查询子句的组合。Bool查询总共包含4种子句。其中,两种会影响算分,另外两种不影响算分。

    子句 类型 影响结果
    must Query Context 必须匹配。贡献算分
    shoud Query Context 选择性匹配,至少满足一条。贡献算分
    must_not Filter Context 过滤子句,必须不能匹配,但不贡献算分
    filter Filter Context 过滤子句,必须匹配,但不贡献算分

    Bool查询语法有以下特点

    1. 子查询可以任意顺序出现
    2. 可以嵌套多个查询,包括bool查询
    3. 如果bool查询中没有must条件,should中必须至少满足一条才会返回结果。
    POST /products/_bulk
    { "index": { "_id": 1 }}
    { "price" : 10,"avaliable":true,"date":"2018-01-01", "productID" : "XHDK-A-1293-#fJ3" }
    { "index": { "_id": 2 }}
    { "price" : 20,"avaliable":true,"date":"2019-01-01", "productID" : "KDKE-B-9947-#kL5" }
    { "index": { "_id": 3 }}
    { "price" : 30,"avaliable":true, "productID" : "JODL-X-1937-#pV7" }
    { "index": { "_id": 4 }}
    { "price" : 30,"avaliable":false, "productID" : "QQPX-R-3956-#aD8" }
    
    # 基本语法
    POST /products/_search
    {
      "query": {
        "bool" : {
          "must" : {
            "term" : { "price" : "30" }
          },
          "filter": {
            "term" : { "avaliable" : "true" }
          },
          "must_not" : {
            "range" : {
              "price" : { "lte" : 10 }
            }
          },
          "should" : [
            { "term" : { "productID.keyword" : "JODL-X-1937-#pV7" } },
            { "term" : { "productID.keyword" : "XHDK-A-1293-#fJ3" } }
          ],
          "minimum_should_match" :1
        }
      }
    }
    

    数组的精确匹配

    在前面章节,我们在查询数组的时候遇到了一个问题,即:默认的查询行为是包含就返回,而不是相等。那么,有没有一种方式可以实现相等的这种场景呢?

    答案是:有的。解决思路就是增加一个count字段用于标识数组内元素的个数,然后通过Bool查询来实现。

    # 改变数据模型,增加字段。解决数组包含而不是精确匹配的问题
    POST /newmovies/_bulk
    { "index": { "_id": 1 }}
    { "title" : "Father of the Bridge Part II","year":1995, "genre":"Comedy","genre_count":1 }
    { "index": { "_id": 2 }}
    { "title" : "Dave","year":1993,"genre":["Comedy","Romance"],"genre_count":2 }
    
    # Query。must,有算分
    POST /newmovies/_search
    {
      "query": {
        "bool": {
          "must": [
            {"term": {"genre.keyword": {"value": "Comedy"}}},
            {"term": {"genre_count": {"value": 1}}}
          ]
        }
      }
    }
    
    # Filter。不参与算分,结果的score是0
    POST /newmovies/_search
    {
      "query": {
        "bool": {
          "filter": [
            {"term": {"genre.keyword": {"value": "Comedy"}}},
            {"term": {"genre_count": {"value": 1}}}
            ]
        }
      }
    }
    

    特别注意:Filter的两种方式,返回的_score都是0,而Query的两种却不是0。

    Bool嵌套查询

    # 嵌套,实现了 should not 逻辑
    POST /products/_search
    {
      "query": {
        "bool": {
          "must": {
            "term": {
              "price": "30"
            }
          },
          "should": [
            {
              "bool": {
                "must_not": {
                  "term": {
                    "avaliable": "false"
                  }
                }
              }
            }
          ],
          "minimum_should_match": 1
        }
      }
    }
    

    查询语句结构的影响

    查询语句的结构,也会对相关度算分产生影响。

    1. 同一层级下的竞争字段,具有相同的权重
    2. 通过嵌套bool查询,可以改变对算分的影响
    POST /animals/_search
    {
      "query": {
        "bool": {
          "should": [
            { "term": { "text": "brown" }},
            { "term": { "text": "red" }},
            { "term": { "text": "quick"   }},
            { "term": { "text": "dog"   }}
          ]
        }
      }
    }
    
    POST /animals/_search
    {
      "query": {
        "bool": {
          "should": [
            { "term": { "text": "quick" }},
            { "term": { "text": "dog"   }},
            {
              "bool":{
                "should":[
                   { "term": { "text": "brown" }},
                   { "term": { "text": "brown" }},
                ]
              }
            }
          ]
        }
      }
    }
    

    Boosting

    # 删除并创建索引
    DELETE news
    POST /news/_bulk
    { "index": { "_id": 1 }}
    { "content":"Apple Mac" }
    { "index": { "_id": 2 }}
    { "content":"Apple iPad" }
    { "index": { "_id": 3 }}
    { "content":"Apple employee like Apple Pie and Apple Juice" }
    
    # 默认的查询,3的记录排在第一
    POST news/_search
    {
      "query": {
        "bool": {
          "must": {
            "match":{"content":"apple"}
          }
        }
      }
    }
    
    # must_not的方式,将3的记录强制排除掉
    POST news/_search
    {
      "query": {
        "bool": {
          "must": {
            "match":{"content":"apple"}
          },
          "must_not": {
            "match":{"content":"pie"}
          }
        }
      }
    }
    
    # 通过Boosting的方式,将3的记录也纳入结果集,只是排名会靠后。
    # positive表示正向激励
    # negative表示负向激励,negative_boost表示激励的比重
    POST news/_search
    {
      "query": {
        "boosting": {
          "positive": {
            "match": {
              "content": "apple"
            }
          },
          "negative": {
            "match": {
              "content": "pie"
            }
          },
          "negative_boost": 0.5
        }
      }
    }
    

    总结

    1. 我们简单地讨论了query contextfilter context,了解了他们的差异。
    2. 我们还学习了bool查询,它可以包含多个子句。
    3. 查询结构的调整会对相关性算分产生影响。
    4. 我们再次通过一个例子学习了boosting,可使用Boosting和Boosting Query的方式对查询的结果进行更精确地控制。

    相关文章

      网友评论

          本文标题:Elasticsearch学习笔记(16) - Query &

          本文链接:https://www.haomeiwen.com/subject/ykwjectx.html