1. 程式人生 > >Elasticsearch Query DSL 整理總結(三)—— Match Phrase Query 和 Match Phrase Prefix Query

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

引數值為 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_prefixmatch_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 敬請期待。

參考文件

1.Match Phrase Query

系列文章列表

Query DSL

  1. Query DSL 概要,MatchAllQuery,全文查詢簡述
  2. Match Query

Java Rest Client API

  1. Elasticsearch Java Rest Client API 整理總結 (一)——Document API
  2. Elasticsearch Java Rest Client API 整理總結 (二) —— SearchAPI
  3. Elasticsearch Java Rest Client API 整理總結 (三)——Building Queries