Elasticsearch學習筆記(16) - Query & Filter

前言

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的方式對查詢的結果進行更精確地控制。
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • 搜索機制 搜索的流程圖如下: 1,文檔寫入ES的時候,ES中會存儲兩份數據。一份是文檔的原始數據,即_source...
    吃火龍果吐芝麻閱讀 2,369評論 0 2
  • 引言 雖然之前做過 elasticsearch 的項目,但是沒有對整個項目的知識點進行過系統的整理。這次趁著對 e...
    零點145閱讀 9,498評論 0 2
  • Query Context & Filter Context 高級搜索的功能:支持多項文本輸入,針對多個字段進行搜...
    辻子路閱讀 2,189評論 0 0
  • Swift1> Swift和OC的區別1.1> Swift沒有地址/指針的概念1.2> 泛型1.3> 類型嚴謹 對...
    cosWriter閱讀 11,145評論 1 32
  • 學校組織的自助餐,雞翅好評,當時剛好餓了,哦哦哦哦薯條也好吃哦哦哦 我吃了八片哈密瓜
    另一個我_1019閱讀 212評論 0 0