Elasticsearch Query DSL 整理總結(三)—— Match Phrase Query 和 Match Phrase Prefix Query
目錄
引言
今天再讀莊子的《逍遙遊》,其中鯤鵬之扶搖直上九萬里之氣勢,蜩(tiao)與學鳩之渺小之對比,令人印象深刻,並對鯤鵬之志心生嚮往。而郭象在注《莊子》卷中卻說,"苟足於其性,則雖大鵬無以自貴於小鳥,小鳥無羨於天池,而榮願有餘矣。故小大雖殊,逍遙一也。"觀看自身,雖然不是什麼領導,老總,但也完全不必感到為職業生涯憂慮,只要熱愛程式設計師這個工作,享受編碼的樂趣,做到 80 歲又有何妨。
書歸正傳,今天我們聊聊 Match Phase Query。
Match Phase Query
match_phrase
查詢針對的是一個語句,比如 "like football", 分析時也會將整個語句作為整體,而不會像上篇的 match 查詢 會將整個語句拆分為單個詞條。
舉個例子,建立一個 match_phase type 並塞進去一個文件, message 是 I like swimming and riding!
PUT matchphasetest {} PUT matchphasetest/_mapping/match_phase { "properties": { "message": { "type": "text" } } } PUT matchphasetest/match_phase/1 { "message": "I like swimming and riding!" } GET matchphasetest/_search { "query": { "match_phrase": { "message": "I like swimming" } } }
預設使用 match_phrase
時會精確匹配查詢的短語,需要全部單詞和順序要完全一樣,標點符號除外。
slop 引數
這種精確匹配在大部分情況下顯得太嚴苛了,有時我們想要包含 ""I like swimming and riding!"" 的文件也能夠匹配 "I like riding"。這時就要以用到 "slop" 引數來控制查詢語句的靈活度。
slop
引數告訴 match_phrase
查詢詞條相隔多遠時仍然能將文件視為匹配 什麼是相隔多遠? 意思是說為了讓查詢和文件匹配你需要移動詞條多少次?
以 "I like swimming and riding!" 的文件為例,想匹配 "I like riding",只需要將 "riding" 詞條向前移動兩次,因此設定 slop
GET matchphasetest/_search
{
"query": {
"match_phrase": {
"message": {
"query": "I like riding",
"slop": 2
}
}
}
}
analyzer 引數
match_phrase
語句也可以設定 analyzer
引數來定義查詢語句時對其中詞條執行的分析過程。
預設情況下,使用的是建立 mapping 時的分析器,如果沒有指定就會使用預設的查詢分析器。這裡舉個例子(只是如何使用)
GET /_search
{
"query": {
"match_phrase" : {
"message" : {
"query" : "this is a test",
"analyzer" : "my_analyzer"
}
}
}
}
zero terms query
match_phrase
也接受 zero_terms_query
為引數,使用方式和 match
查詢語句相同
Match Phrase 字首查詢
match_phrase_prefix
和 match_phrase
用法是一樣的,區別就在於它允許對最後一個詞條字首匹配。以上節的資料為例,查詢 I like sw
就能匹配到
I like swimming and riding
。
GET matchphasetest/_search
{
"query": {
"match_phrase_prefix": {
"message": "I like swi"
}
}
}
max_expansions
官方文件中說 match_phrase_prefix
查詢中有個引數 max_expansions
說的是引數 max_expansions
控制著可以與字首匹配的詞的數量,預設值是 50。
以 I like swi
查詢為例,它會先查詢第一個與字首 swi
匹配的詞,然後依次查詢蒐集與之匹配的詞(按字母順序),直到沒有更多可匹配的詞或當數量超過 max_expansions
時結束。
但是我在使用時,故意造出了數十個以 swi
開頭的詞,而將 max_expansions
的值設為 10。但是卻返回了所有的結果。在 elasitc 官網也有對該問題的討論, 也是沒有找到答案。這個問題作為一個公案權且記下,如果您知道原因,麻煩告訴我,非常感謝。
這裡也貼出個例子,以備後面排查
GET matchphaseprefixtest/_search
{
"query": {
"match": {
"message": {
"query": "I like sw",
"max_expansions": 10
}
}
}
}
match_phrase_prefix
用起來非常方便,能夠實現輸入即搜尋的效果,但是也會出現問題。 假如說查詢 I like s
並且想要匹配 I like swimming
,結果是預設情況下它會搜尋出前 50 個組合,如果前 50 個沒有 swimming
,那就不會顯示出結果。只能是使用者繼續輸入後面的字母才可能匹配出結果。
要實現更好的即使搜尋的特性,可以看看 completion suggester 和
Index-Time Search-as-You-Type 能不能實現。
小結
本文論述了 Match Phase Query 和 Match Phrase 字首查詢 的使用,下文會講解 Multi Match Query 敬請期待。