elasticsearch best_fields most_fields cross_fields從內在實現看區別——本質就是前兩者是以field為中心,后者是詞條為中心


1.最佳字段(Best fields)::

假設我們有一個讓用戶搜索博客文章的網站(允許多字段搜索,最佳字段查詢),就像這兩份文檔一樣:

PUT /my_index/my_type/1 { "title": "Quick brown rabbits", "body": "Brown rabbits are commonly seen." } PUT /my_index/my_type/2 { "title": "Keeping pets healthy", "body": "My quick brown fox eats rabbits on a regular basis." } 

// SENSE: 110_Multi_Field_Search/15_Best_fields.json

用戶輸入了"Brown fox",文檔2匹配的更好一些,因為它包含了用戶尋找的兩個單詞。

{
    "multi_match": { "query": "Quick brown fox", "type": "best_fields", <1> "fields": [ "title", "body" ], "tie_breaker": 0.3, "minimum_should_match": "30%" <2> } }
2.多數字段(Most fields)::

一個用來調優相關度的常用技術是將相同的數據索引到多個字段中。它用來盡可能多地匹配文檔。

考慮一下most_fields查詢是如何執行的:ES會為每個字段生成一個match查詢,然后將它們包含在一個bool查詢中。

我們可以將查詢傳入到validate-query API中進行查看:

GET /_validate/query?explain
{
  "query": { "multi_match": { "query": "Poland Street W1V", "type": "most_fields", "fields": [ "street", "city", "country", "postcode" ] } } } 

// SENSE: 110_Multi_Field_Search/40_Entity_search_problems.json

它會產生下面的解釋(explaination):

(street:poland   street:street   street:w1v)
(city:poland     city:street     city:w1v)
(country:poland  country:street  country:w1v)
(postcode:poland postcode:street postcode:w1v)

你可以發現能夠在兩個字段中匹配poland的文檔會比在一個字段中匹配了poland和street的文檔的分值要高。

3.跨字段(Cross fields)::

對於一些實體,標識信息會在多個字段中出現,每個字段中只含有一部分信息:

  • Person: first_name 和 last_name
  • Book: titleauthor, 和 description
  • Address: streetcitycountry, 和 postcode

此時,我們希望在任意字段中找到盡可能多的單詞。我們需要在多個字段中進行查詢,就好像這些字段是一個字段那樣。

用戶也許會搜索名為"Peter Smith"的人,或者名為"Poland Street W1V"的地址。每個查詢的單詞都出現在不同的字段中

如果你在索引文檔前就能夠自定義_all字段的話,那么使用_all字段就是一個不錯的方法。但是,ES同時也提供了一個搜索期間的解決方案:使用類型為cross_fields的multi_match查詢。cross_fields類型采用了一種以詞條為中心(Term-centric)的方法,這種方法和best_fields及most_fields采用的以字段為中心(Field-centric)的方法有很大的區別。它將所有的字段視為一個大的字段,然后在任一字段中搜索每個詞條。

為了闡述以字段為中心和以詞條為中心的查詢的區別,看看以字段為中心的most_fields查詢的解釋(譯注:通過validate-query API得到):

GET /_validate/query?explain
{
    "query": { "multi_match": { "query": "peter smith", "type": "most_fields", "operator": "and", <1> "fields": [ "first_name", "last_name" ] } } } 

// SENSE: 110_Multi_Field_Search/50_Cross_field.json

<1> operator設為了and,表示所有的詞條都需要出現。

對於一份匹配的文檔,peter和smith兩個詞條都需要出現在相同的字段中,要么是first_name字段,要么是last_name字段:

(+first_name:peter +first_name:smith)
(+last_name:peter  +last_name:smith)

而以詞條為中心的方法則使用了下面這種邏輯:

+(first_name:peter last_name:peter) +(first_name:smith last_name:smith) 

換言之,詞條peter必須出現在任一字段中,同時詞條smith也必須出現在任一字段中。

cross_fields類型首先會解析查詢字符串來得到一個詞條列表,然后在任一字段中搜索每個詞條。僅這個區別就能夠解決在以字段為中心的查詢中提到的3個問題中的2個,只剩下倒排文檔頻度的不同這一問題。

幸運的是,cross_fields類型也解決了這個問題,從下面的validate-query請求中可以看到:

GET /_validate/query?explain
{
    "query": { "multi_match": { "query": "peter smith", "type": "cross_fields", <1> "operator": "and", "fields": [ "first_name", "last_name" ] } } } 

// SENSE: 110_Multi_Field_Search/50_Cross_field.json

<1> cross_fields 使用以詞條為中心(Term-centric)進行匹配。

它通過混合(Blending)字段的倒排文檔頻度來解決詞條頻度的問題:

+blended("peter", fields: [first_name, last_name])
+blended("smith", fields: [first_name, last_name])

換言之,它會查找詞條smith在first_name和last_name字段中的IDF值,然后使用兩者中較小的作為兩個字段最終的IDF值。因為smith是一個常見的姓氏,意味着它也會被當做一個常見的名字。

提示:為了讓cross_fields查詢類型能以最佳的方式工作,所有的字段都需要使用相同的解析器。使用了相同的解析器的字段會被組合在一起形成混合字段(Blended Fields)。

如果你包含了使用不同解析鏈(Analysis Chain)的字段,它們會以和best_fields相同的方式被添加到查詢中。比如,如果我們將title字段添加到之前的查詢中(假設它使用了一個不同的解析器),得到的解釋如下所示:

(+title:peter +title:smith)
(
  +blended("peter", fields: [first_name, last_name])
  +blended("smith", fields: [first_name, last_name])
)

當使用了minimum_should_match以及operator參數時,這一點尤為重要。

摘自:https://es.xiaoleilu.com/110_Multi_Field_Search/50_Cross_field.html

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM