【相關性搜索】 多字段搜索的兩種方式——詞中心與字段中心

背景

  • 首先看個例子,有兩個 doc,一條是 albino elephant,一條是 elephant elephant
PUT test_elephant/_doc/1
{
  "title_text":"elephant",
  "body_text":"elephant"
}

PUT test_elephant/_doc/2
{
  "title_text":"albino",
  "body_text":"elephant"
}
複製代碼
  • 用戶想查 albino elephant , 因而咱們就這樣寫了一條 query 語句,指望能夠召回 doc 2
GET test_elephant/_search
{
  "query": {
    "query_string": {
      "fields": ["title_text","body_text"],
      "query": "albino elephant"
    }
  }
}
複製代碼
  • 可是實際結果卻和咱們預期的不同,兩個 doc 評分如出一轍,那麼這是爲何呢?

  • 首先 expalin 一下能夠看到
doc1 max(title_text:elephant,body_text:elephant)
doc2 max(title_text:albino,body_text:elephant)
複製代碼
  • 而由於 elephant 和 albino 在 title 字段中都出現了一次,因此分數同樣,都是0.69
  • 那麼爲何呢?
    • 咱們經過 _validate/query?rewrite=true 能夠看到這個 query 被翻譯成
      image.png

以字段爲中心(field-centric) VS 以詞爲中心(term-centric)

  • 上述的那個例子就是以字段爲中心中經典的『白化象問題』,那麼到底什麼是以字段爲中心,什麼是以詞爲中心呢?下圖

  • 左邊是爲 以字段爲中心,可見,字段爲中心爲query 在各個字段分別算分,而後按必定 function 求最終結果,也就是其實最終的結果也是整個 query 在哪一個字段中表現最好。
    • 這種適用於用戶意圖只會命中一個字段時適用
    • 優點:符合結構化語義,易於控制不一樣字段權重
    • 問題:
      • 白化象問題(albino elephant) — 有更多搜索詞匹配的文檔沒有被排在靠前的位置
      • 信號衝突(signal discordance) — 多字段 idf 不一,排序難被用戶理解。好比一我的常常作演員不多作導演,而後搜索的時候,導演字段的分數就會很是高,形成當導演的電影排序靠前,形成用戶困擾
  • 右邊爲 以詞爲中心,以詞爲中心則是詞在不一樣字段中的分數,經過必定 function 算出(圖中爲 max),而後再將各個詞的分數以必定 function 結合做爲總分。
    • 這種實際上就是用戶並不關係匹配的是什麼字段,不關心文檔結構,關心的只是匹配到了哪些詞。
    • 優點:更符合用戶心智,用戶每每難以瞭解數據的結構
    • 問題:很差控制不一樣字段權重,實現複雜

ES 中的多字段檢索方式

查看真實檢索語句

  • 利用 _validate/query?rewrite=true 能夠看到真實傳個 lucene 的語句,即可看出其真實邏輯。也可用explain=true能夠看見部分中間過程,可是效果沒有 rewrite 直觀

image.png
image.png

經常使用多字段檢索

  • 下面利用 validate 對 title(keyword 字段) , title_text(ik 分詞器) 和 body_text(ik 分詞器) 進行查詢,查詢內容爲 ZSearch 通用搜索
  • MultiMatch
    • best_fields - 字段中心,字段間 max ,可用 tie_breaker 調整字段間關係
      • (title:ZSearch 通用搜索 | (title_text:zsearch title_text:通用 title_text:搜索) | (body_text:zsearch body_text:通用 body_text:搜索))
    • most_fields - 字段中心 字段間相加
      • title:ZSearch 通用搜索 (title_text:zsearch title_text:通用 title_text:搜索) (body_text:zsearch body_text:通用 body_text:搜索)
    • cross_fields - 詞中心 詞在不一樣字段間取 max,而後相加
      • (((title_text:zsearch | body_text:zsearch) (title_text:通用 | body_text:通用) (title_text:搜索 | body_text:搜索)) | title:ZSearch 通用搜索)
  • QueryString - 字段中心 同 best_fields
    • (title:ZSearch 通用搜索 | (title_text:zsearch title_text:通用 title_text:搜索) | (body_text:zsearch body_text:通用 body_text:搜索))
  • SimpleQueryString 詞中心,但詞在不一樣字段間爲相加
    • (title_text:zsearch title:ZSearch body_text:zsearch) ((title_text:通用 title_text:搜索) title:通用搜索 (body_text:通用 body_text:搜索))
  • 須要注意的是詞爲中心的查詢方式均會受分詞器影響,其中 simple query string 和 cross 採起了兩種不一樣的實現方式
    • simple query string 爲簡單按空格分割,而後直接丟入各字段進行查詢,所以是分詞前的以詞爲中心,而不是最終的,及時設置了 analyzer 也依舊如此
    • cross_field 則是採起首先按分詞器進行分組,一樣的分詞器內以詞爲中心在多字段進行查詢,不一樣的分詞器直接按字段取 max
  • 另外,多字段查詢的minimum_should_match也只與一級子句(最外邊的括號內的)有關,內部再分詞均不會做用

擴展閱讀

如何實現字段中心和詞中心相結合

  1. 類似字段,按用戶意圖將字段分組,好比 姓 和 名 兩個字段合併 姓名 一個字段,將不一樣意圖的搜索徹底分開
  2. 以詞爲中心進行兜底,以字段爲中心進行加成,以下

image.png

多字段算分在信息檢索領域的嘗試

  • 傳統BM25在計算相關性時把文檔當作整體來考慮,但隨着搜索技術的發展。文檔慢慢的被結構化數據所取代。每一個文檔都會被切分紅多個獨立的域,尤爲是垂直化的搜索。好比網頁有可能被切分紅標題,內容,主題詞等域,這些域對文章主題的貢獻不能同等對待,因此權重就要有所偏重。
  • BM25沒有考慮這點。因此BM25F在此基礎上作了一些改進,就是再也不單單的將單詞做爲個體考慮,而且將文檔也依照field劃分爲個體考慮,因此BM25F是每個單詞在各個field中分值的加權求和。

image.png

參考資料

相關文章
相關標籤/搜索