# Elasticsearch QueryString 查詢語法筆記
最近開始想把 LOG 儲存在 Elasticsearch 裡,但這樣做需要有個方便查詢的 UI 介面,對我而言 Kibana 功能過於複雜,Postman 查詢又比較麻煩。後來發現了 Elasticvue 這個工具,選擇它的原因是它支援多種瀏覽器擴充套件及桌面應用程式版本。
[Elasticvue](https://github.com/cars10/elasticvue) 的查詢介面主要基於 query_string 語法,這是 Elasticsearch 中基於 Lucene 查詢語法的擴展版本。對熟悉 SQL 的使用者來說,`query_string` 比其他 DSL 語法更容易上手,因此我整理了一些常用的語法方便查閱。
可從 [Elasticvue 官網](https://elasticvue.com/) 查看各個瀏覽器擴充套件,或是桌面應用程式的安裝檔案或連結。
## 基本語法
### 基本 API 結構
```json
{
"query": {
"query_string": {
"query": "your query string here", // 必要參數:查詢字串(使用 "*" 可搜尋所有文件)
"default_field": "content", // 選用參數:預設搜尋欄位,未指定則搜尋全部欄位
"default_operator": "OR" // 選用參數:預設運算符,預設值為 OR
// 其他可選參數
}
},
"size": 10, // 選用參數:回傳結果數量,預設為 10
"from": 0, // 選用參數:起始位置,預設為 0
"sort": [] // 選用參數:結果排序
}
```
未指定欄位時,QueryString 會在所有可搜尋欄位中進行搜尋。
## 查詢語法
### 1. 基本搜尋
簡單關鍵字搜尋:
```
apple
```
多個詞彙(預設使用 OR 連接):
```
apple banana
```
精確片語搜尋(使用雙引號):
```
"red apple"
```
### 2. 布林運算符
AND 運算符(兩個詞都必須存在):
```
apple AND banana
```
OR 運算符(至少有一個詞必須存在):
```
apple OR banana
```
NOT 運算符(排除包含某詞的文件):
```
apple NOT banana
```
加號(必須包含此詞):
```
+apple banana
```
減號(必須排除此詞):
```
apple -banana
```
### 3. 欄位指定查詢
針對特定欄位搜尋:
```
title:apple
```
針對多個欄位的查詢:
```
title:apple AND content:banana
```
多值查詢(OR 條件):
```
user_id:(1234 OR 5678)
```
欄位存在性查詢:
```
_exists_:email // 查詢 email 欄位存在的文件,可以理解成不為 null
NOT _exists_:phone // 查詢 phone 欄位不存在的文件,可以理解成為 null
```
欄位指定優先順序:查詢字串中明確指定欄位 > fields 參數 > default_field 參數。
### 4. 範圍查詢與比較運算符
範圍查詢:
```
price:[10 TO 20] // 閉區間,包含 10 和 20
price:{10 TO 20} // 開區間,不包含 10 和 20
price:[10 TO *] // 大於等於 10
price:[* TO 20] // 小於等於 20
```
比較運算符:
```
price:>10 // 大於 10
price:>=10 // 大於等於 10
price:<20 // 小於 20
price:<=20 // 小於等於 20
```
這兩種寫法在功能上通常等價,可依情境選擇使用。
### 5. 萬用字元搜尋
萬用字元搜尋:
```
te?t // 問號代表一個字元
test* // 星號代表零個或多個字元
```
## 重要參數
### 1. 欄位相關參數
**default_field vs fields**:
* `default_field`: 指定預設搜尋的單一欄位。
* `fields`: 指定多個搜尋欄位及其權重。
```json
// 使用 default_field
{
"query_string": {
"query": "apple",
"default_field": "content"
}
}
// 使用 fields
{
"query_string": {
"query": "apple",
"fields": ["title^2", "content", "tags"]
}
}
```
### 2. analyze_wildcard
控制是否對萬用字元表達式進行分析處理:
* `analyze_wildcard: false`(預設):萬用字元表達式不經過分析器處理。
* `analyze_wildcard: true`:萬用字元表達式先經過分析器處理,可實現大小寫不敏感搜尋。
```json
{
"query_string": {
"query": "Te*",
"analyze_wildcard": true,
"analyzer": "standard"
}
}
```
### 3. analyzer
指定如何處理和分析查詢字串:
```json
{
"query_string": {
"query": "The Quick Brown Fox",
"analyzer": "standard"
}
}
```
analyzer 在 text 與 keyword 類型欄位上的差異:
* text 欄位:分析器會分詞並通常轉換為小寫。
* keyword 欄位:通常保留原始格式,需要特殊處理才能實現大小寫不敏感。
### 4. auto_generate_synonyms_phrase_query
控制同義詞處理方式:
* `true`(預設):自動為同義詞生成片語查詢,保持詞序和相鄰性。
* `false`:只生成普通同義詞查詢,不考慮詞序。
例如,若設定 "ny" 與 "new york" 為同義詞:
```json
{
"query_string": {
"query": "ny restaurants",
"auto_generate_synonyms_phrase_query": true
}
}
```
* true:會匹配 "ny restaurants" 或 "new york restaurants"("new york" 作為整體片語)。
* false:會匹配 "ny restaurants" 或 "new restaurants" 或 "york restaurants"。
### 5. 權重控制:boost 與欄位加權
Elasticsearch 提供兩種方式來控制搜尋權重:
**1. boost 參數**:調整整個查詢的權重。
```json
{
"query_string": {
"query": "apple iphone",
"boost": 2.0
}
}
```
* 功能:增加整個查詢的重要性。
* 主要用途:
* 在複合查詢結構中調整當前 query_string 查詢相對於其他查詢子句的重要性。
* 與欄位加權結合使用,同時控制查詢級別和欄位級別的權重。
**2. 欄位加權**:使用 `^` 語法調整特定欄位的權重。
```json
{
"query_string": {
"query": "apple iphone",
"fields": ["title^3", "description^2", "content"]
}
}
```
* 功能:增加特定欄位的相對重要性。
* 適用場景:當在多個欄位中搜尋相同關鍵詞,但某些欄位應更重要時。
* 說明:在上例中,title 欄位的匹配權重是 content 欄位的 3 倍,description 是 2 倍。
**兩者結合使用的例子**:
```json
{
"query_string": {
"query": "apple",
"fields": ["title^3", "description"],
"boost": 2.0
}
}
```
在這個例子中:
* 欄位加權:控制 title 欄位相對 description 欄位的重要性。
* boost:控制整個 query_string 查詢的整體權重(在更大的查詢結構中)。
**差異**:
* `boost`:控制整個查詢的權重。
* 欄位加權 `^`:控制查詢內不同欄位間的相對權重。
### 6. 模糊搜尋(fuzziness 與 phrase_slop)
波浪號 `~` 在 QueryString 中有兩種不同用途,取決於它的位置:
**1. 模糊搜尋(單詞後的波浪號)**:
```
apple~ // 單詞後接波浪號,表示模糊搜尋
apple~2 // 指定模糊度為 2
```
* 對應參數:`fuzziness`
* 功能:處理單個詞的拼寫錯誤,基於編輯距離。
* 識別方式:用於**單詞**後面。
**2. 近似搜尋(片語後的波浪號)**:
```
"apple banana"~5 // 片語後接波浪號,表示近似搜尋
```
* 對應參數:`phrase_slop`
* 功能:處理片語中詞的順序和距離。
* 識別方式:用於**引號包圍的片語**後面。
**在 API 中設定這些參數**:
```json
{
"query_string": {
"query": "apple~2 \"quick fox\"~3",
"fuzziness": "AUTO", // 全域設定,會被查詢中的具體值覆蓋
"phrase_slop": 2 // 全域設定,會被查詢中的具體值覆蓋
}
}
```
**fuzziness 設定差異**:
* `"fuzziness": "AUTO"`:根據詞長自動調整(1-2字元:0錯誤,3-5字元:1錯誤,>5字元:2錯誤)。
* `"fuzziness": 2`:固定允許最多2個字元編輯距離。
**範例說明**:
* `apple~1` 可匹配 "aple", "appla" 等拼寫錯誤的詞。
* `"quick fox"~3` 可匹配 "quick brown fox"(中間有詞)或 "fox is quick"(順序變化)。
**優先順序**:
* 查詢字串中使用 `~` 設定的值會覆蓋 API 參數中的全域設定。
## 日期時間查詢
基本日期範圍搜尋:
```
timestamp:[2023-01-01 TO 2023-01-31]
```
相對時間搜尋:
```
timestamp:>now-1d // 過去24小時
```
常用相對時間表達式:
* `now-1h`:一小時前。
* `now-1w`:一週前。
* `now/d`:今天開始。
* `now/w`:本週開始。
* `now/M`:本月開始。
範圍語法vs比較運算符:
```
// 兩種等價的寫法
timeStamp:[\"2025-01-01T00:00\" TO *]
timeStamp:>=\"2025-01-01T00:00\"
```
日期時間格式:
* 標準格式:`yyyy-MM-ddTHH:mm:ss.SSSZ`。
* 簡化格式:`yyyy-MM-dd`。
* 注意時區設定,預設為 UTC。
## 分頁與排序
在查詢中加入分頁參數:
```json
{
"query": {
"query_string": {
"query": "apple"
}
},
"from": 0, // 起始位置
"size": 10, // 每頁數量
"sort": [
{ "price": "asc" }, // 按價格升序
"_score" // 相同價格按相關性排序
]
}
```
## 實用範例
### 1. 複雜布林組合查詢
```json
{
"query": {
"query_string": {
"query": "(title:apple OR description:apple) AND (price:[500 TO 1000] OR brand:\"Apple Inc.\")",
"default_operator": "AND"
}
}
}
```
### 2. 模糊搜尋與時間範圍組合
```json
{
"query": {
"query_string": {
"query": "phne~ AND date:[now-30d TO now]",
"fields": ["title", "content"]
}
}
}
```
### 特殊字元轉義
QueryString 中有許多特殊字元具有特定含義,若要作為普通字元使用,需要使用反斜線 `\` 轉義:
```
\+ \- \= \&\& \|\| \> \< \! \( \) \{ \} \[ \] \^ \" \~ \* \? \: \\ \/
```
例如:
* 搜尋包含加號的文件:`title:\+1`
* 搜尋包含括號的文件:`content:\(sample\)`
* 搜尋包含引號的文件:`description:\"quoted text\"`
###### tags: `ELK` `Elasticsearch`