筆記目錄

Skip to content

Elasticsearch Query DSL 查詢語法筆記

TLDR

  • Query DSL 優勢:相比 Query String,DSL 支援 Nested 查詢、地理空間查詢、自訂評分及複雜的布林邏輯,且結構清晰易於維護。
  • Match Query:全文檢索核心,minimum_should_match 僅在 OR 邏輯下有效,且保底值為 1。
  • Multi Match:提供 best_fields(預設,取最高分)、most_fields(加總分數)、cross_fields(跨欄位搜尋)等多種策略。
  • Combined Fields:以詞彙為中心,將多個 text 欄位視為單一欄位,適合跨欄位搜尋。
  • Nested Query:解決 object 型別扁平化導致的關聯性丟失問題,必須用於 nested 型別欄位。
  • 日期範圍查詢:建議統一使用字串格式,並利用 Date Math(如 ||/d)處理捨入,避免數值與字串混用導致的解析錯誤。
  • 效能警示wildcardregexp 查詢效能較差,應盡量避免使用前導萬用字元或複雜的正規表達式。

Query DSL vs Query String

在正式環境中,Query DSL(Domain Specific Language)因其 JSON 結構化特性,能提供比 Query String 更強大的功能與更明確的錯誤回饋。

1. 功能差異

某些進階功能僅能透過 Query DSL 實作:

  • Nested 查詢:保留巢狀物件內部欄位關聯。
  • 地理空間查詢:如 geo_distance
  • 自訂評分:使用 function_score 客製化相關性評分。
  • 複雜布林邏輯:透過 bool 組合 mustshouldmust_notfilter

常用 Query DSL 語法

1. Match Query - 全文檢索查詢

用於全文檢索,會進行分詞與相關性評分。

minimum_should_match 參數

此參數僅在 operator = "OR" 時有效,用於控制至少需符合的條件數量。

  • 特殊規則:最少符合數保底為 1。當設定 -4-100% 時,至少需符合 1 個詞。
  • 百分比計算:採用「無條件捨去法」。例如 4 個詞設定 75%,4 × 0.75 = 3.0,至少需符合 3 個;設定 74%,4 × 0.74 = 2.96,無條件捨去為 2 個。
  • 多條件組合:格式如 2<-25% 9<-3,代表 ≤ 2 個 token 時需 100% 符合;3-9 個 token 時最多遺漏 25%;> 9 個 token 時最多遺漏 3 個。

lenient 參數

控制型別不符時的行為:

  • false(預設):拋出錯誤,查詢失敗。
  • true:忽略該欄位查詢,不會拋出錯誤,但該欄位無匹配結果。

2. Multi Match Query - 多欄位查詢

在多個欄位中搜尋相同關鍵字。

  • best_fields:取最高分欄位分數(預設)。
  • most_fields:加總所有欄位分數。
  • cross_fields:將多個欄位視為一個大欄位,適合姓名、地址等跨欄位匹配。

WARNING

當欄位 search_analyzer 設定不一致時,cross_fields 的行為會改變,可能導致所有詞必須在同一個欄位中出現。


3. Combined Fields Query - 跨欄位詞彙查詢

採用以詞彙為中心的方式,將多個 text 欄位視為單一組合欄位。

  • 限制:所有欄位必須是 text 型別且使用相同的 search_analyzer
  • 執行邏輯:每個詞必須至少在一個欄位中出現(可分散在不同欄位)。

4. Range Query - 範圍查詢

用於數值與日期查詢。

  • 日期格式陷阱:若 index mapping 有指定 format,查詢參數必須與之對齊,或使用 format 參數覆寫。
  • 數值與字串混用:數值永遠被解釋為毫秒時間戳記,建議統一使用字串格式(如 "2025-01-01")以避免解析錯誤。
  • 時間精度問題:若只提供到小時(如 2023-01-15T08),Elasticsearch 會將文件與查詢參數格式化至相同精度。建議明確指定完整時間或使用 Date Math 捨入功能(如 ||/h)。

5. Nested Query - 巢狀物件查詢

用於查詢 nested 型別欄位,解決 object 型別扁平化導致的關聯性丟失。

  • 什麼情況下會遇到這個問題:當資料結構為陣列(如訂單中的商品列表),且需要確保「商品名稱」與「對應價格」在同一個陣列元素內匹配時。
  • 解決方案:將欄位定義為 nested 型別,並使用 nested 查詢。
json
{
  "query": {
    "nested": {
      "path": "comments",
      "query": {
        "bool": {
          "must": [
            { "term": { "comments.author": "John" }},
            { "term": { "comments.rating": 3 }}
          ]
        }
      }
    }
  }
}

6. Fuzzy Query - 模糊查詢

容錯查詢,允許拼字錯誤。

  • 建議做法:對於 text 欄位,優先使用 match 查詢搭配 fuzziness 參數,而非直接使用 fuzzy 查詢,因為 match 會經過分析器處理,更符合搜尋需求。

7. Regexp Query - 正規表達式查詢

效能最差,應盡量避免。

  • 錨點限制:不支援 ^$ 錨點運算子,正規表達式必須匹配整個字串。
  • 特殊字元:若需匹配 # 等特殊字元,需使用雙反斜線 \\ 跳脫(如 \\#)。

異動歷程

  • 2025-11-04 初版文件建立。