Multi Match Query
Multi Match Query
multi_match查詢建議在match query之上,並允許多字段查詢:
GET /_search { "query": { "multi_match" : { "query": "this is a test", 【1】 "fields": [ "subject", "message" ] 【2】 } } }
【1】 查詢字符串
【2】被查詢的字段
fields
and per-field boosting
字段可以通過通配符指定,例如:
GET /_search { "query": { "multi_match" : { "query": "Will Smith", "fields": [ "title", "*_name" ] 【1】 } } }
【1】查詢title,first_name和last_name字段。
個別字段可以通過插入符號(^)來提升:
GET /_search { "query": { "multi_match" : { "query" : "this is a test", "fields" : [ "subject^3", "message" ] 【1】 } } }
【1】subject字段是message字段的3倍。
Types of multi_match
query:
內部執行multi_match查詢的方式依賴於type參數,它可以被設置成:
best_fields (默認)查找與任何字段匹配的文檔,但使用最佳字段中的_score。看best_fields.
most_fields 查找與任何字段匹配的文檔,並聯合每個字段的_score.
cross_fields 采用相同分析器處理字段,就好像他們是一個大的字段。在每個字段中查找每個單詞。看cross_fields。
phrase 在每個字段上運行match_phrase查詢並和每個字段的_score組合。看phrase and phrase_prefix。
phrase_prefix 在每個字段上運行match_phrase_prefix查詢並和每個字段的_score組合。看phrase and phrase_prefix。
best_fields
當你在同一個字段中搜索最佳查找的多個單詞時,bese_fields類型是最有效的。例如,"brown fox"單獨在一個字段中比"brown"在一個字段中和"for"在另外一個字段中更有意義。
best_fields為每一個字段生成match query並在dis_max查詢中包含他們,以發現單個最匹配的字段。例如這個查詢:
GET /_search { "query": { "multi_match" : { "query": "brown fox", "type": "best_fields", "fields": [ "subject", "message" ], "tie_breaker": 0.3 } } }
也可以這樣執行:
GET /_search { "query": { "dis_max": { "queries": [ { "match": { "subject": "brown fox" }}, { "match": { "message": "brown fox" }} ], "tie_breaker": 0.3 } } }
通常best_fields類型使用單個最佳匹配字段的score,但是假如tie_breaker被指定,則它通過以下計算score:
- 來自最佳匹配字段的score
- 相加所有其他匹配字段的tie_breaker * _score。
同時也接受analyzer
, boost
, operator
, minimum_should_match
, fuzziness
, lenient
, prefix_length
, max_expansions
, rewrite
, zero_terms_query和cutoff_frequency作為匹配查詢的解釋。
重要:operator
和 minimum_should_match
best_fields和most_fields類型是field-centric( 他們為每一個字段生成匹配查詢)。這意味著為每一個字段單獨提供operator和
minimum_should_match參數,這可能不是你想要的。
以此查詢為例:
GET /_search { "query": { "multi_match" : { "query": "Will Smith", "type": "best_fields", "fields": [ "first_name", "last_name" ], "operator": "and" 【1】 } } }
【1】所有的項必須存在
該查詢也可以這樣執行:
(+first_name:will +first_name:smith) | (+last_name:will +last_name:smith)
換句話說,所有項必須在單個字段中存在,以匹配文檔。查看cross_fields以尋找更好的解決方案。
most_fields
當查詢使用不同方式包含相同文本分析的多個字段時,most_fields類型是非常有用的。例如,main字段可能包含synonyms,stemming 和沒有變音符的項,second字段可能包含original項和third字段包含shingles。通過組合來自三個字段的score,我們能盡可能多的通過main字段匹配文檔,但是使用second和third字段將最相似的結果推送到列表的頂部。
該查詢:
GET /_search { "query": { "multi_match" : { "query": "quick brown fox", "type": "most_fields", "fields": [ "title", "title.original", "title.shingles" ] } } }
可能執行如下:
GET /_search { "query": { "bool": { "should": [ { "match": { "title": "quick brown fox" }}, { "match": { "title.original": "quick brown fox" }}, { "match": { "title.shingles": "quick brown fox" }} ] } } }
每一個match子句的score將被加在一起,然後通過match子句的數量來分割。
也接受analyzer
, boost
, operator
, minimum_should_match
, fuzziness
, lenient
, prefix_length
, max_expansions
, rewrite
, zero_terms_query和cutoff_frequency,作為match query中的解釋,但請看operator and minimum_should_match。
phrase
and phrase_prefix
phrase和phrase_prefix類型行為就像best_fields,但他們使用
match_phrase或者
match_phrase_prefix查詢代替match查詢。
該查詢:
GET /_search { "query": { "multi_match" : { "query": "quick brown f", "type": "phrase_prefix", "fields": [ "subject", "message" ] } } }
可能執行如下:
GET /_search { "query": { "dis_max": { "queries": [ { "match_phrase_prefix": { "subject": "quick brown f" }}, { "match_phrase_prefix": { "message": "quick brown f" }} ] } } }
也接受analyzer
, boost
, lenient
, slop
和zero_terms_query作為在match query中的解釋。
phrase_prefix類型此外接受max_expansions。
重要:phrase,phrase_prefix和fuzziness:fuzziness參數不能被phrase和phrase_prefix類型使用
cross_fields
cross_fields類型對於多個字段應該匹配的結構文檔特別有用。例如,當為“Will Smith”查詢first_name和
last_name字段時,最佳匹配應該是"Will"在一個字段中並且"Smith"在另外一個字段中。
這聽起來像most_fields的工作,但這種方法有兩個問題。第一個問題是operator和minimum_should_match在每個前綴字段中作用,以代替前綴項(請參考explanation above)。 第二個問題是與關聯性有關:在first_name和last_name字段中不同的項頻率可能導致不可預期的結果。 例如,想像我們有兩個人,“Will Smith”和"Smith Jones"。“Smith”作為姓是非常常見的(所以重要性很低),但是“Smith”作為名字是非常不常見的(所以重要性很高)。 假如我們搜索“Will Smith”,則“Smith Jones”文檔可能顯示在更加匹配的"Will Smith"上,因為first_name:smith的得分已經勝過first_name:will加last_name:smith的總分。
處理該種類型查詢的一種方式是簡單的將first_name和last_name索引字段放入單個full_name字段中。當然,這只能在索引時間完成。
cross_field類型嘗試通過采用term-centric方法在查詢時解決這些問題。首先把查詢字符串分解成當個項,然後在任何字段中查詢每個項,就好像它們是一個大的字段。
查詢就像這樣:
GET /_search { "query": { "multi_match" : { "query": "Will Smith", "type": "cross_fields", "fields": [ "first_name", "last_name" ], "operator": "and" } } }
被執行為:
+(first_name:will last_name:will) +(first_name:smith last_name:smith)
換一種說法,所有的項必須至少在匹配文檔中一個字段中出現(比較the logic used for best_fields and most_fields)。
解決了兩個問題中的一個。通過混合所有字段項的頻率解決不同項匹配的問題,以便平衡差異。
在實踐中,first_name:smith將被視為和last_name:smith具有相同的頻率,加1。這將使得在first_name和last_name上的匹配具有可比較的分數,對於last_name具有微小的優勢,因為它是最有可能包含simth的字段。
註意,cross_fields通常僅作用與得到1提升的短字符串字段。 否則增加,項頻率和長度正常化有助於得分, 使得項統計的混合不再有任何意義。
假如你通過Validata API運行上面的查詢,將返回這樣的解釋:
+blended("will", fields: [first_name, last_name]) +blended("smith", fields: [first_name, last_name])
也接受analyzer
, boost
, operator
, minimum_should_match
, lenient
, zero_terms_query
和cutoff_frequency
,作為match query的解釋。
cross_field
and analysis
cross_field類型只能在具有相同分析器的字段上以term-centric模式工作。具有相同分析器的字段如上述實例組合在一起。假如有多個組,則他們使用bool查詢相結合。
例如,假如我們有相同分析器的first和last字段,增加一個同時使用edge_ngram分析器的first.edge和last.edge,該查詢:
GET /_search { "query": { "multi_match" : { "query": "Jon", "type": "cross_fields", "fields": [ "first", "first.edge", "last", "last.edge" ] } } }
可能被執行為:
blended("jon", fields: [first, last]) | ( blended("j", fields: [first.edge, last.edge]) blended("jo", fields: [first.edge, last.edge]) blended("jon", fields: [first.edge, last.edge]) )
換句話說,first和last可能被組合在一起並被當做一個字段來對待,同時first.edge和last.edge可能被組合在一起並當做一個字段來對待。
具有多個組是好的,當使用operator或者minimum_should_match關聯的時候,它可能遭受和most_fields和best_fields相同的問題。
你可以容易的將該查詢重寫為兩個獨立的cross_fields查詢與bool查詢相結合,並將minimum_should_match參數應用於其中一個:
GET /_search { "query": { "bool": { "should": [ { "multi_match" : { "query": "Will Smith", "type": "cross_fields", "fields": [ "first", "last" ], "minimum_should_match": "50%" 【1】 } }, { "multi_match" : { "query": "Will Smith", "type": "cross_fields", "fields": [ "*.edge" ] } } ] } } }
【1】will或smith必須存在於first或last字段。
你可以通過在查詢中指定analyzer參數強制把所有字段放入相同組中。
GET /_search { "query": { "multi_match" : { "query": "Jon", "type": "cross_fields", "analyzer": "standard", 【1】 "fields": [ "first", "last", "*.edge" ] } } }
【1】對所有字段使用standard分析器
將執行如下:
blended("will", fields: [first, first.edge, last.edge, last]) blended("smith", fields: [first, first.edge, last.edge, last])
tie_breaker
默認情況,每一個per-term混合查詢將使用組中任何字段的最佳分數,然後將這些分數相加,以得出最終分數。tie_breaker參數可以改變per-term混合查詢的默認行為,它接受:
0.0 獲取最好的分數(舉例)first_name:will和last_name:will(default)
1.0 所有分數相加(舉例)first_name:will和last_name:will
0.0 < n < 1.0 將單個最佳分數加上tie_breaker乘以其它每個匹配字段的分數。
重要:cross_fields
and fuzziness
fuzziness參數不能被cross_fields類型使用。
原文地址:https://www.elastic.co/guide/en/elasticsearch/reference/5.0/query-dsl-multi-match-query.html
Multi Match Query