引言
今天再讀庄子的《逍遙游》,其中鯤鵬之扶搖直上九萬里之氣勢,蜩(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 參數值為 2, 就可以匹配到。
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_phrase_prefix": {
"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 敬請期待。
