Elastic學習之旅 (8) 深入詞項和全文搜索

大家好,我是Edison。

上一篇:Elastic學習之旅 (7) 聚合分析

相信很多童鞋和我一樣,有點傻傻分不清Term查詢和全文查詢的區別,那麼今天我們就來一起梳理一下。

基於Term的查詢

Term(詞項)是ES中表達語義的最小單位,搜索和利用統計語言模型進行自然語言處理都需要處理Term。

ES中Term Query包含了: 

Term Query / Range Query / Exist Query / Prefix Query / Wildcard Query

ES中Term的特點:

特點1:在ES中,Term查詢對輸入不做分詞。換句話說,它會將輸入作爲一個整體,在倒排索引中查找準確的詞項,並且使用相關度算分公式爲每個包含該詞項的文檔進行相關度算分 - 例如“Apple Store”。

可能上面有點難理解,現在我們通過一個實例來理解。

首先,我們先插入幾條示例數據:

POST /products/_bulk
{ "index":{"_id":1}}
{ "productID": "XHDK-A-1293-#fJ3", "desc":"iPhone"}
{ "index":{"_id":2}}
{ "productID": "KDKE-B-9947-#kL5", "desc":"iPad"}
{ "index":{"_id":3}}
{ "productID": "J0DL-X-1937-#pV7", "desc":"MBP"}

然後,我們通過以下Term Query查詢desc爲iPhone的記錄:

POST /products/_search
{
  "query":{
    "term": {
      "desc": {
        "value": "iPhone"
      }
    }
  }
}

當你執行這條查詢後,你會發現,ES居然沒有查到這條記錄,明明我們剛剛插入的就是它啊!

別急,這恰恰是因爲Term查詢不對輸入做分詞,會將輸入作爲一個整體,進而導致我們搜索不到。
我們進一步將上面的查詢改爲以下方式就可以查詢到記錄:將iPhone改爲全小寫的iphone即可。

POST /products/_search
{
  "query":{
    "term": {
      "desc": {
        "value": "iphone" 
      }
    }
  }
}

同時,如果我們想實現一個精確匹配,我們可以使用term的keyword關鍵字來實現,如下查詢所示:精確匹配一個productID。這也說明,在ES中通過keyword關鍵字查詢,它也不會做分詞處理。

POST /products/_search
{
  "query":{
    "term": {
      "productID.keyword": {
        "value": "XHDK-A-1293-#fJ3"
      }
    }
  }
}

我們還會發現,Term查詢會返回一個算分:0.9808292,代表匹配的精準度。

特點2:可以使用Constant Score將查詢轉換成一個Filtering,避免算分,並利用緩存,提高性能。

剛剛提到ES會在倒排索引中進行相關性算分,這在一定程度上會帶來一些查詢上的開銷。我們可以通過ConstantScore將Query轉成Filter,來避免相關性算分的開銷,還可以有效利用緩存,提高查詢的效率!

POST /products/_search
{
  "explain": true,
  "query": {
    "constant_score": {
      "filter": {
        "term": {
          "productID.keyword": {
            "value": "XHDK-A-1293-#fJ3"
          }
        }
      }
    }
  }
}

查詢結果顯示也可以證明它會跳過算分步驟:

基於全文的查詢

基於全文的查詢,ES提供了以下Query(我們在第6篇Query DSL中學習的就是全文查詢):

Match Query / Match Phrase Query / Query String Query

基於全文的查詢具有以下的特點:

特點1:索引和搜索時都會進行分詞,查詢字符串先傳到一個合適的分詞器,然後生成一個待查詢的詞項列表。

特點2:查詢會對每個詞項進行底層的查詢,再將結果進行合併,還會爲每個文檔生成一個算分。

針對這兩個特點,我們通過一個示例來串一下:

例如,查詢“Matrix reloaded”,會查到包括Matrix或者reload的所有結果。

首先,構建一個Match Query:

POST /movies/_search
{
  "query": {
    "match": {
      "title": {
        "query": "Matrix reloaded"
      }
    }
  }
}

ES會返回title字段中包括Matrix 或者 reloaded的所有記錄:

其次,如果你希望查詢title字段中同時包含Matrix reloaded,那你可以修改默認的operator爲AND來提高精準度:

POST /movies/_search
{
  "profile": "true", 
  "query": {
    "match": {
      "title": {
        "query": "Matrix reloaded",
        "operator": "AND"
      }
    }
  }
}

然後,如果你希望查詢的是隻要出現Matrix 和 reloaed,其中間可以間隔一些單詞,那麼你也可以使用match phrase 和 slop參數設置分詞出現的最大間隔距離:

POST /movies/_search
{
  "profile": "true", 
  "query": {
    "match_phrase": {
      "title": {
        "query": "Matrix reloaded",
        "slop": 1
      }
    }
  }
}

最後,這個基於全文的查詢在ES中的基本查詢過程如下所示:

小結

本篇,我們瞭解了ElasticSearch的Term和全文查詢的基本概念及其特點,利用這些特點在指定的場景會有是事半功倍的效果!

參考資料

極客時間,阮一鳴,《ElasticSearch核心技術與實戰

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章