lucene-query-syntax
Lucene Query Syntax -- Elasticsearch における Lucene クエリ構文 完全ガイド
対象読者: Elasticsearch / Kibana を利用するエンジニア、SRE、データアナリスト 前提知識: Elasticsearch の基本的なインデックス・ドキュメント概念 環境: Elasticsearch 8.x / Kibana 8.x (7.x 系でも大部分は共通)
目次
- はじめに -- Lucene Query Syntax とは
- Elasticsearch クエリ言語の中での位置づけ
- 基本構文
- 範囲検索 (Range Search)
- ブーリアン演算子 (Boolean Operators)
- 必須・除外演算子 (+/-)
- ワイルドカード検索
- 正規表現検索
- あいまい検索 (Fuzzy Search)
- 近接検索 (Proximity Search)
- ブースティング (Boosting)
- グルーピング (括弧による論理構造)
- 特殊文字のエスケープ
- Kibana での Lucene 有効化方法
- KQL vs Lucene 比較表
- Lucene と KQL の使い分け
- 実践ユースケース
- 制限事項と注意点
- まとめ
1. はじめに -- Lucene Query Syntax とは
1.1 概要
Lucene Query Syntax は、Apache Lucene ライブラリが提供するテキスト検索用のクエリ言語である。 Elasticsearch は内部で Apache Lucene を検索エンジンとして使用しており、 Lucene のクエリパーサーをそのまま利用できるインターフェースを公開している。
Elasticsearch の query_string クエリおよび Kibana の検索バーにおいて、
この Lucene Query Syntax を直接記述して検索を行うことができる。
1.2 歴史的背景
Elasticsearch 初期のバージョン (1.x - 5.x) では、Kibana の検索バーは Lucene Query Syntax がデフォルトであった。 Kibana 7.0 以降、KQL (Kibana Query Language) がデフォルトとなったが、 Lucene は引き続きサポートされており、KQL では表現できない高度な検索パターンに対して 重要な役割を果たしている。
1.3 Elasticsearch API での使用
Lucene Query Syntax は REST API からも query_string クエリとして使用可能である。
GET /my-index/_search
{
"query": {
"query_string": {
"query": "status:200 AND extension:php",
"default_field": "message"
}
}
}
simple_query_string を使う場合は構文エラーに対して寛容な動作となる。
GET /my-index/_search
{
"query": {
"simple_query_string": {
"query": "status:200 + extension:php",
"default_field": "message"
}
}
}
2. Elasticsearch クエリ言語の中での位置づけ
Elasticsearch には複数のクエリ言語が存在する。それぞれ用途が異なる。
| クエリ言語 | 主な用途 | 使用場所 | 特徴 |
|---|---|---|---|
| Lucene Query Syntax | テキスト検索 (高度) | Kibana 検索バー, query_string API | 正規表現・あいまい検索・近接検索が可能 |
| KQL (Kibana Query Language) | テキスト検索 (簡易) | Kibana 検索バー (デフォルト) | オートコンプリート対応、構文が簡潔 |
| Query DSL | プログラマティック検索 | REST API | JSON 形式、最も柔軟 |
| EQL (Event Query Language) | イベントシーケンス検索 | REST API, Kibana Security | 時系列イベントの相関分析 |
| **ES | QL** | パイプベースのデータ探索 | Kibana Discover, REST API |
| SQL | リレーショナルスタイル検索 | REST API, JDBC/ODBC | SQL に慣れたユーザー向け |
2.1 Lucene の立ち位置
Lucene Query Syntax は上記の中で 最も歴史が長く、かつ テキスト検索の表現力が最も高い 文字列ベースの構文である。 特に以下の点で KQL を上回る:
- 正規表現検索 (
/pattern/) - あいまい検索 (
word~,word~2) - 近接検索 (
"word1 word2"~N) - ブースティング (
field:value^N) - 範囲検索の排他指定 (
{400 TO 499})
3. 基本構文
3.1 フリーテキスト検索
最も基本的な検索は、検索バーにキーワードをそのまま入力する方法である。
error
この場合、デフォルトフィールド (通常は _all または message) に対して「error」というトークンを含むドキュメントが検索される。
server error
スペース区切りで複数のキーワードを入力すると、デフォルトでは OR 検索となる。 つまり「server」または「error」のいずれかを含むドキュメントがヒットする。
3.2 フィールド指定検索 (field:value)
特定のフィールドに対して検索する場合は field:value の形式を使う。
status:200
HTTP ステータスコード 200 のドキュメントを検索する。
response.status_code:500
ネストされたフィールド名もドット区切りで指定できる。
host.name:web-server-01
ホスト名が web-server-01 であるドキュメントを検索する。
3.3 フレーズ検索 (Phrase Search)
ダブルクォーテーションで囲むと、その語順どおりのフレーズを検索する。
"connection refused"
「connection」の直後に「refused」が来るドキュメントのみがヒットする。
単に connection refused と入力した場合は OR 検索となり、
どちらか一方だけを含むドキュメントもヒットしてしまう点に注意。
message:"out of memory"
フィールド指定とフレーズ検索を組み合わせることもできる。
3.4 複数の基本構文の組み合わせ
status:200 AND message:"request completed"
host.name:web-* AND status:500
extension:php OR extension:html
4. 範囲検索 (Range Search)
数値・日付・文字列フィールドに対して範囲検索を行える。
4.1 閉区間 (Inclusive Range) -- 角括弧 [ TO ]
上限と下限の 両方を含む 範囲検索には角括弧 [] を使用する。
status:[400 TO 499]
HTTP ステータスコード 400 以上 499 以下のドキュメントを検索する。
bytes:[1000 TO 5000]
レスポンスサイズが 1000 バイト以上 5000 バイト以下のドキュメントを検索する。
4.2 開区間 (Open-ended Range) -- ワイルドカードとの組み合わせ
片側だけの範囲を指定する場合はワイルドカード * を使う。
status:[500 TO *]
ステータスコード 500 以上のすべてのドキュメント。
status:[* TO 299]
ステータスコード 299 以下のすべてのドキュメント。
@timestamp:[2025-01-01 TO *]
2025 年 1 月 1 日以降のすべてのドキュメント。
@timestamp:[2025-01-01T00:00:00 TO 2025-01-31T23:59:59]
2025 年 1 月中のドキュメントを日時精度で検索。
4.3 排他区間 (Exclusive Range) -- 波括弧 { TO }
上限や下限を 含まない 範囲検索には波括弧 {} を使用する。
status:{400 TO 499}
ステータスコード 401 以上 498 以下 (400 と 499 は含まない)。
bytes:{0 TO 1000}
0 より大きく 1000 より小さいバイト数。
4.4 混合区間 -- 角括弧と波括弧の組み合わせ
片方を含み、もう片方を含まない指定も可能。
status:[400 TO 499}
400 以上 499 未満 (400 は含む、499 は含まない)。
bytes:{0 TO 5000]
0 より大きく 5000 以下。
4.5 日付範囲の実践例
@timestamp:[now-1h TO now]
直近 1 時間のログを検索 (Elasticsearch date math 対応)。
@timestamp:[now-7d/d TO now/d]
過去 7 日間 (日単位で丸めた範囲)。
@timestamp:[2025-03-01 TO 2025-03-31]
2025 年 3 月のログを検索。
5. ブーリアン演算子 (Boolean Operators)
5.1 AND 演算子
両方の条件を満たすドキュメントを検索する。
status:200 AND extension:php
注意: AND は 大文字 で記述する必要がある。and (小文字) はキーワードとして扱われてしまう。
host.name:web-01 AND status:500 AND message:"timeout"
複数の AND を連結できる。
5.2 OR 演算子
いずれかの条件を満たすドキュメントを検索する。
status:404 OR status:500
注意: OR も 大文字 で記述する。
extension:php OR extension:html OR extension:js
5.3 NOT 演算子
条件を満たさないドキュメントを検索する。
status:200 AND NOT extension:css
NOT status:200
すべてのドキュメントからステータスコード 200 のものを除外する。
5.4 演算子の優先順位
Lucene の演算子優先順位は以下のとおりである:
NOT(最も高い)ANDOR(最も低い)
したがって、以下のクエリ:
status:200 OR status:301 AND extension:php
は、以下と同じ意味になる:
status:200 OR (status:301 AND extension:php)
意図した動作にするため、括弧を使って優先順位を明示する ことを強く推奨する。
5.5 複合ブーリアンクエリの例
(status:500 OR status:502 OR status:503) AND host.name:production-*
本番環境のサーバーエラーを検索。
(extension:php OR extension:py) AND NOT status:200 AND bytes:[1000 TO *]
PHP または Python で、成功以外のレスポンスで、サイズが 1000 バイト以上のもの。
6. 必須・除外演算子 (+/-)
6.1 必須演算子 (+)
+ 演算子は、その条件が 必ず含まれなければならない ことを示す。
+status:200
ステータスコード 200 のドキュメントのみを返す。
+status:200 +extension:php
ステータスコード 200 かつ 拡張子が php のドキュメントのみを返す。
これは status:200 AND extension:php と同等である。
6.2 除外演算子 (-)
- 演算子は、その条件に 一致するドキュメントを除外する ことを示す。
-extension:css
拡張子が css のドキュメントを除外する。
+status:200 -extension:css -extension:js
ステータスコード 200 で、CSS と JavaScript を除外する。
6.3 AND/OR/NOT との違い
| 構文 | 等価表現 | 意味 |
|---|---|---|
+A +B | A AND B | A と B の両方を含む |
+A -B | A AND NOT B | A を含み B を含まない |
A B | A OR B | A または B を含む |
+A B | (特殊) | A は必須、B はオプション (スコアに影響) |
最後の +A B のパターンに注意が必要である。これは「A は必ず含むが、B を含むドキュメントはスコアが高くなる」という意味になり、AND でも OR でもない独特の動作をする。
6.4 実践例
+host.name:web-server-01 +status:[500 TO 599] -message:"health check"
web-server-01 のサーバーエラーから、ヘルスチェック関連を除外する。
+extension:log -message:"DEBUG" -message:"TRACE"
ログファイルから DEBUG と TRACE レベルのメッセージを除外する。
7. ワイルドカード検索
7.1 アスタリスク (*) -- 0 文字以上の任意の文字列
host.name:web-*
「web-」で始まるすべてのホスト名にマッチする。
message:*error*
「error」を含むすべてのメッセージにマッチする。
extension:p*
「p」で始まるすべての拡張子 (php, py, png など) にマッチする。
7.2 クエスチョンマーク (?) -- 任意の 1 文字
status:40?
400, 401, 402, ..., 409 にマッチする。
host.name:web-0?
web-01, web-02, ..., web-09 にマッチする。
extension:?s
js, ts, cs など 2 文字で「s」で終わる拡張子にマッチする。
7.3 ワイルドカードの組み合わせ
host.name:*-prod-??
名前に「-prod-」を含み、末尾が 2 文字のホスト名。
url.path:*/api/v?/*
API バージョン 1 桁のパスにマッチする。
7.4 注意事項
- 先頭のワイルドカード (
*error) はパフォーマンスが著しく低下する可能性がある。 Elasticsearch は転置インデックスを使用しているため、先頭一致は効率的だが、 中間一致・末尾一致はすべてのトークンをスキャンする必要がある。 - Kibana の設定で先頭ワイルドカードが無効化されている場合がある。
- 大量のドキュメントに対するワイルドカード検索はクラスターに負荷をかける。
7.5 ワイルドカードとフレーズ検索の違い
message:connect* -- "connection", "connected", "connecting" など
"connect*" -- フレーズ検索ではワイルドカードは展開されない
message:connect* -- 正しい使い方
ワイルドカードはフレーズ検索 (ダブルクォート内) では使用できない点に注意する。
8. 正規表現検索
8.1 基本構文
Lucene は正規表現をスラッシュ / で囲んで記述する。
message:/[Ee]rror [0-9]+/
「Error 404」「error 500」などのパターンにマッチする。
host.name:/web-[0-9]{2}/
web-01, web-02, ..., web-99 にマッチする。
8.2 サポートされる正規表現パターン
Lucene の正規表現エンジンは Apache Lucene regexp であり、 PCRE (Perl Compatible Regular Expressions) とは異なる点がある。
| パターン | 説明 | 例 |
|---|---|---|
. | 任意の 1 文字 | /err.r/ -> error, errir |
* | 直前のパターンの 0 回以上の繰り返し | /er*or/ -> eor, eror, error |
+ | 直前のパターンの 1 回以上の繰り返し | /er+or/ -> eror, error |
? | 直前のパターンの 0 回または 1 回 | /colou?r/ -> color, colour |
{n} | 直前のパターンのちょうど n 回 | /[0-9]{3}/ -> 200, 404, 500 |
{n,m} | 直前のパターンの n 回以上 m 回以下 | /[0-9]{1,3}/ -> 1, 42, 500 |
[abc] | 文字クラス | /[45][0-9]{2}/ -> 400-599 |
[^abc] | 否定文字クラス | /[^2][0-9]{2}/ -> 200 以外の 3 桁 |
(abc) | グループ化 | `/(error |
| | OR | /(GET|POST)/ -> GET, POST |
^ | 非対応 | Lucene regexp では行頭マッチ非対応 |
$ | 非対応 | Lucene regexp では行末マッチ非対応 |
\d, \w, \s | 非対応 | 文字クラスショートカット非対応 |
8.3 注意事項
- Lucene の正規表現はフィールド全体 (アナライズ後のトークン全体) に対してマッチする。
^(行頭) と$(行末) は暗黙的に付与されている。\d,\wなどのショートカットは使えないため、[0-9],[a-zA-Z0-9_]と記述する。- 正規表現検索はパフォーマンスが低くなる可能性がある。
8.4 実践例
url.path:/\/api\/v[0-9]+\/users\/[0-9]+/
/api/v1/users/12345 のようなパスにマッチする。
message:/timeout after [0-9]+ (seconds|ms)/
タイムアウトメッセージを秒またはミリ秒単位で検索する。
status:/[45][0-9]{2}/ AND host.name:/prod-.*/
本番環境の 4xx/5xx エラーを検索する。
9. あいまい検索 (Fuzzy Search)
9.1 基本構文 -- チルダ ~
あいまい検索はレーベンシュタイン距離 (編集距離) に基づいて、 タイポ (打ち間違い) やスペルミスを含む文字列を検索する。
message:connecton~
「connecton」(n が 1 つ多い) → 「connection」がヒットする。
message:recieve~
「recieve」(よくあるスペルミス) → 「receive」がヒットする。
9.2 編集距離の指定 -- ~N
チルダの後に数値を指定して、許容する編集距離を制御できる。
message:connecton~1
編集距離 1 以内の文字列を検索する。1 文字の挿入・削除・置換・転置が許容される。
message:conection~2
編集距離 2 以内。「conection」→「connection」(2 文字の差異) がヒットする。
9.3 レーベンシュタイン距離の説明
レーベンシュタイン距離とは、ある文字列を別の文字列に変換するために必要な 最小の編集操作 (挿入・削除・置換) の回数である。
| 元の文字列 | 対象文字列 | 編集距離 | 操作 |
|---|---|---|---|
connecton | connection | 1 | 「i」の挿入 |
recieve | receive | 1 | 「ie」→「ei」の転置 |
conection | connection | 2 | 「n」の挿入 + 「i」の挿入 |
eror | error | 1 | 「r」の挿入 |
serach | search | 1 | 「a」と「r」の転置 |
9.4 デフォルト値
チルダのみ (~) を指定した場合、デフォルトの編集距離は 2 である。
message:eror~ -- 編集距離 2 (デフォルト)
message:eror~1 -- 編集距離 1
message:eror~2 -- 編集距離 2 (明示的)
9.5 パフォーマンスへの影響
- 編集距離が大きいほど、マッチする候補が指数的に増加する。
- Lucene は編集距離の最大値を 2 に制限している (3 以上は指定できない)。
- あいまい検索は内部的にオートマトンを構築するため、通常の完全一致検索より遅い。
9.6 実践例
message:authentcation~ AND status:[400 TO 499]
認証エラー (タイポを含む可能性あり) を 4xx ステータスで検索する。
host.name:prodction~ AND status:500
ホスト名のタイポを許容して本番環境のエラーを検索する。
10. 近接検索 (Proximity Search)
10.1 基本構文
近接検索は、フレーズ検索にチルダと数値を加えた構文である。 指定した距離内に 2 つ以上のキーワードが出現するドキュメントを検索する。
"quick fox"~5
「quick」と「fox」が 5 語以内の距離で出現するドキュメントを検索する。
10.2 通常のフレーズ検索との違い
| 構文 | マッチする例 | マッチしない例 |
|---|---|---|
"quick fox" | "the quick fox" | "the quick brown fox" |
"quick fox"~1 | "the quick brown fox" | "the quick very brown fox" |
"quick fox"~3 | "the quick very fast brown fox" | (距離 3 以内なら何でも) |
10.3 語順の反転
近接検索では語順の反転も許容される。ただし、反転には追加のスロップ (距離) が消費される。
"fox quick"~5
「fox」の後に「quick」が来る場合でもマッチする。 ただし語順の反転には 2 スロップ分の距離が消費される。
10.4 フィールド指定との組み合わせ
message:"connection timeout"~3
message フィールド内で「connection」と「timeout」が 3 語以内で出現するドキュメント。
message:"database error"~5 AND host.name:prod-*
本番環境のデータベースエラー (近接) を検索する。
10.5 実践例
message:"out memory"~2
「out of memory」「out-of-memory」「out from memory」などにマッチする。
message:"failed connect"~3 AND status:[500 TO 599]
接続失敗関連のサーバーエラーを検索する。
message:"disk space"~2
「disk space」「disk free space」「disk available space」にマッチする。
11. ブースティング (Boosting)
11.1 基本構文 -- キャレット ^
ブースティングは、特定の条件に より高いスコア (関連性) を与える機能である。 検索結果の 順序 (ランキング) に影響する。
title:elasticsearch^3
title フィールドの「elasticsearch」のスコアを 3 倍にする。
11.2 複数フィールドでのブースティング
title:elasticsearch^3 description:elasticsearch
title に「elasticsearch」がある場合はスコアが 3 倍、 description にある場合は通常の 1 倍。 両方にある場合は合計スコアで順位が決まる。
11.3 ブースト値
| ブースト値 | 意味 |
|---|---|
^1 | デフォルト (通常のスコア) |
^2 | スコアが 2 倍 |
^5 | スコアが 5 倍 |
^0.5 | スコアが半分 (降格) |
^10 | スコアが 10 倍 (強い優先) |
11.4 フレーズのブースティング
message:"connection refused"^5 OR message:"connection timeout"^2
「connection refused」の重要度を「connection timeout」より高く設定する。
11.5 実践例
(title:error^3 OR message:error) AND status:[500 TO 599]
タイトルにエラーが含まれるドキュメントをより上位に表示する。
message:"OutOfMemoryError"^10 OR message:"StackOverflowError"^5 OR message:"NullPointerException"^2
重大度の順にエラーのランキングを制御する。
12. グルーピング (括弧による論理構造)
12.1 基本構文
括弧 () を使って、クエリの論理構造を明示的に制御する。
(status:404 OR status:500) AND host.name:production
括弧がないと、演算子の優先順位により意図しない結果になる場合がある。
12.2 括弧なしの場合の問題
status:404 OR status:500 AND host.name:production
これは以下と等価になる (AND が OR より優先):
status:404 OR (status:500 AND host.name:production)
つまり、ステータス 404 のドキュメントは host.name に関係なくすべてヒットしてしまう。
12.3 ネストされたグルーピング
((status:500 OR status:502) AND host.name:prod-*) OR ((status:404) AND url.path:/api/*)
複雑な条件を構造化できる。
12.4 フィールドのグルーピング
同一フィールドに対する複数条件をグループ化する。
status:(404 OR 500 OR 502 OR 503)
これは以下と等価だが、より簡潔である:
status:404 OR status:500 OR status:502 OR status:503
12.5 実践例
(host.name:web-* OR host.name:api-*) AND (status:[500 TO 599]) AND NOT (message:"health check" OR message:"ping")
Web サーバーと API サーバーのサーバーエラーから、ヘルスチェックとピングを除外する。
(extension:php AND status:500) OR (extension:py AND status:502)
PHP の 500 エラーまたは Python の 502 エラーを検索する。
13. 特殊文字のエスケープ
13.1 エスケープが必要な文字
Lucene Query Syntax では以下の文字が特殊文字として扱われる。
これらの文字をリテラルとして検索する場合はバックスラッシュ \ でエスケープする。
+ - = && || > < ! ( ) { } [ ] ^ " ~ * ? : \ /
13.2 エスケープの例
message:C\+\+
「C++」を検索する場合、+ をエスケープする必要がある。
url.path:\/api\/v1\/users
URL パスのスラッシュをエスケープする。
message:error\: connection refused
コロンをエスケープする。
message:\(critical\)
括弧をエスケープする。
message:file\.txt
ドットをエスケープする (ドットは正規表現以外では特殊文字ではないが、明示的にエスケープすることが推奨される)。
13.3 ダブルクォーテーション内での扱い
フレーズ検索のダブルクォーテーション内では、多くの特殊文字はリテラルとして扱われる。
message:"error: connection refused"
ただし、ダブルクォーテーション自体を検索する場合はエスケープが必要:
message:\"quoted text\"
13.4 よくある間違いと対処法
| 検索したい文字列 | 間違い | 正しい |
|---|---|---|
C++ | C++ | C\+\+ または "C++" |
file.log | file.log | file\.log または "file.log" |
status:OK | status:OK (フィールド検索になる) | "status:OK" |
10.0.0.1 | 10.0.0.1 | "10.0.0.1" |
user@example.com | user@example.com | "user@example.com" |
14. Kibana での Lucene 有効化方法
14.1 Kibana 7.x / 8.x でのデフォルト設定
Kibana 7.0 以降、検索バーのデフォルトクエリ言語は KQL (Kibana Query Language) である。 Lucene を使用するには、明示的に切り替える必要がある。
14.2 切り替え手順
- Kibana の Discover ページ (または Dashboard の検索バー) を開く。
- 検索バーの左側にある 「KQL」 ボタンをクリックする。
- ドロップダウンメニューが表示される。
- 「Lucene」 を選択する。
- 検索バーの左側の表示が「Lucene」に切り替わる。
- Lucene Query Syntax でクエリを入力できるようになる。
検索バー: [KQL ▼] [____________________] [🔍 Search]
↓ クリック
[KQL]
[Lucene] ← これを選択
↓
[Lucene ▼] [____________________] [🔍 Search]
14.3 デフォルト言語の変更
管理者が Kibana のデフォルト検索言語を変更するには:
- Management > Advanced Settings に移動する。
- Search セクションの
search:queryLanguageを探す。 - 値を
kueryからluceneに変更する。 - Save changes をクリックする。
14.4 注意事項
- KQL と Lucene では構文が異なるため、切り替え後にクエリを書き直す必要がある。
- KQL で記述したクエリは Lucene モードでは正しく解釈されない場合がある。
- 保存済み検索やダッシュボードのフィルターは、作成時のクエリ言語で保存される。
- チーム内で使用するクエリ言語を統一することを推奨する。
15. KQL vs Lucene 比較表
15.1 機能比較
| 機能 | KQL | Lucene | 備考 |
|---|---|---|---|
| フリーテキスト検索 | error | error | 同一 |
| フィールド指定 | status: 200 | status:200 | KQL はコロン後にスペース可 |
| フレーズ検索 | message: "connection refused" | message:"connection refused" | 同一 |
| AND 演算子 | and (小文字可) | AND (大文字必須) | KQL は大文字小文字不問 |
| OR 演算子 | or (小文字可) | OR (大文字必須) | KQL は大文字小文字不問 |
| NOT 演算子 | not (小文字可) | NOT (大文字必須) | KQL は大文字小文字不問 |
| ワイルドカード (*) | host.name: web-* | host.name:web-* | 同一 |
| 範囲検索 (数値) | bytes >= 1000 | bytes:[1000 TO *] | KQL の方が直感的 |
| 範囲検索 (日付) | @timestamp >= "2025-01-01" | @timestamp:[2025-01-01 TO *] | KQL の方が直感的 |
| 排他的範囲検索 | 非対応 | status:{400 TO 499} | Lucene のみ |
| 正規表現検索 | 非対応 | message:/[Ee]rror [0-9]+/ | Lucene のみ |
| あいまい検索 | 非対応 | message:connecton~ | Lucene のみ |
| 近接検索 | 非対応 | "quick fox"~5 | Lucene のみ |
| ブースティング | 非対応 | title:error^3 | Lucene のみ |
| +/- 演算子 | 非対応 | +status:200 -extension:css | Lucene のみ |
| ネストされたフィールド | user.name: "john" | 制限あり | KQL が優れている |
| オートコンプリート | 対応 | 非対応 | KQL のみ |
| フィールド候補表示 | 対応 | 非対応 | KQL のみ |
| 値の候補表示 | 対応 | 非対応 | KQL のみ |
| 構文エラーの寛容さ | 高い | 低い | KQL はエラーに寛容 |
15.2 構文の対比例
| 検索意図 | KQL | Lucene |
|---|---|---|
| ステータスが 200 | status: 200 | status:200 |
| ステータスが 200 以外 | not status: 200 | NOT status:200 |
| ステータスが 400-499 | status >= 400 and status <= 499 | status:[400 TO 499] |
| ステータスが 500 以上 | status >= 500 | status:[500 TO *] |
| ホスト名が web- で始まる | host.name: web-* | host.name:web-* |
| メッセージに error を含む | message: error | message:error |
| エラーフレーズ検索 | message: "out of memory" | message:"out of memory" |
| 複合条件 | status: 200 and extension: php | status:200 AND extension:php |
| 正規表現検索 | 不可能 | message:/[0-9]{3}\.[0-9]{1,3}/ |
| あいまい検索 | 不可能 | message:recieve~ |
16. Lucene と KQL の使い分け
16.1 KQL を使うべきケース
以下のケースでは KQL が推奨される:
- 日常的なログ検索: シンプルなフィルタリングやキーワード検索
- 初学者: オートコンプリートの支援があり学習コストが低い
- ダッシュボードのフィルター: 簡易な条件設定
- 範囲検索:
>=,<=の直感的な構文 - ネストされたオブジェクト: KQL の方がネストフィールドの扱いが優れている
16.2 Lucene を使うべきケース
以下のケースでは Lucene が推奨される:
- 正規表現による高度なパターン検索: IP アドレスパターン、URL パターン等
- タイポ・スペルミスを含むログの検索: あいまい検索が有効
- テキストの近接分析: 特定のキーワードが近くに出現するパターンの検出
- 検索結果のランキング制御: ブースティングによるスコア調整
- 排他的な範囲検索: 境界値を含まない厳密な範囲指定
- 複雑なブーリアン条件: +/- 演算子を活用した柔軟な条件設定
16.3 判断フローチャート
検索要件の判断:
│
├── 正規表現が必要? ──→ YES ──→ Lucene
├── あいまい検索が必要? ──→ YES ──→ Lucene
├── 近接検索が必要? ──→ YES ──→ Lucene
├── ブースティングが必要? ──→ YES ──→ Lucene
├── 排他的範囲が必要? ──→ YES ──→ Lucene
│
├── シンプルな条件? ──→ YES ──→ KQL
├── オートコンプリートが欲しい? ──→ YES ──→ KQL
├── ネストフィールド? ──→ YES ──→ KQL
│
└── いずれにも該当しない ──→ KQL (デフォルト推奨)
17. 実践ユースケース
17.1 ユースケース 1: 正規表現によるログ検索
シナリオ: 特定のパターンの IP アドレスからのアクセスを検索したい。
client.ip:/10\.0\.[0-9]+\.[0-9]+/
10.0.x.x のプライベート IP アドレスからのアクセスを検索する。
client.ip:/192\.168\.1\.(1[0-9]{2}|2[0-4][0-9]|25[0-5])/ AND status:[400 TO 599]
192.168.1.100 - 192.168.1.255 からのエラーアクセスを検索する。
シナリオ: 特定の形式のエラーコードを含むログを検索したい。
message:/ERR-[A-Z]{3}-[0-9]{4}/
「ERR-ABC-1234」形式のエラーコードを検索する。
message:/(ORA|SQL)-[0-9]{4,5}/
Oracle (ORA-xxxxx) または SQL Server (SQL-xxxx) のエラーコードを検索する。
17.2 ユースケース 2: タイポ (打ち間違い) を許容した検索
シナリオ: ユーザーが入力したログメッセージにタイポが含まれている可能性がある。
message:authentcation~ AND status:401
「authentication」のタイポを許容して、認証失敗を検索する。
message:connetion~ AND message:refusd~
「connection refused」のタイポを許容して検索する。
シナリオ: ホスト名の入力ミスを考慮した検索。
host.name:productin~ AND status:[500 TO 599]
「production」のタイポを許容して本番環境のエラーを検索する。
17.3 ユースケース 3: 近接分析によるコンテキスト検索
シナリオ: 特定のキーワードが近くに出現するログを検索したい。
message:"database timeout"~3
「database」と「timeout」が 3 語以内で出現するログを検索する。 以下のようなメッセージがマッチする:
- "database connection timeout"
- "database query timeout"
- "timeout while accessing database"
message:"memory allocation failed"~5
メモリ割り当て失敗に関連するログを広範囲に検索する。
message:"ssl certificate expired"~4 AND host.name:prod-*
本番環境の SSL 証明書関連の問題を検索する。
17.4 ユースケース 4: 関連性チューニング (ブースティング)
シナリオ: エラーログの優先順位付けを行いたい。
message:"OutOfMemoryError"^10 OR message:"StackOverflowError"^8 OR message:"NullPointerException"^5 OR message:"IOException"^3 OR message:"TimeoutException"^2
重大度の順にエラーをランキングする。
シナリオ: 特定のフィールドを重視した検索を行いたい。
title:elasticsearch^5 OR tags:elasticsearch^3 OR body:elasticsearch
タイトルにキーワードがあるドキュメントを最優先で表示する。
17.5 ユースケース 5: 複合的なログ分析
シナリオ: 本番環境のサーバーエラーを包括的に分析したい。
(host.name:prod-* OR host.name:production-*) AND status:[500 TO 599] AND NOT (message:"health check" OR message:"readiness probe" OR message:"liveness probe") AND @timestamp:[now-1h TO now]
直近 1 時間の本番環境のサーバーエラー (ヘルスチェック除外) を検索する。
シナリオ: API のパフォーマンス問題を調査したい。
url.path:/\/api\/v[12]\/.*/ AND response_time:[1000 TO *] AND status:200 AND NOT url.path:*health*
応答に 1 秒以上かかった API リクエスト (成功レスポンスのみ) を検索する。
17.6 ユースケース 6: セキュリティ調査
シナリオ: 不審なアクセスパターンを検索したい。
url.path:/\/(wp-admin|phpmyadmin|\.env|\.git)/ AND status:[200 TO 299]
一般的な脆弱性スキャン対象へのアクセス成功を検索する。
message:/(SELECT|INSERT|UPDATE|DELETE).*FROM/ AND NOT user.name:admin
SQL インジェクションの可能性があるリクエストを検索する。
client.ip:/[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+/ AND status:401 AND @timestamp:[now-1h TO now]
直近 1 時間の認証失敗を IP アドレス別に検索する。
18. 制限事項と注意点
18.1 ネストされたオブジェクトの制限
Lucene Query Syntax は、Elasticsearch の nested 型フィールドに対する検索に制限がある。
// ドキュメント例
{
"user": {
"name": "John",
"age": 30
},
"comments": [
{ "author": "Alice", "text": "Great post" },
{ "author": "Bob", "text": "Nice article" }
]
}
Lucene では nested 型のフィールドに対して cross-object matching の制御ができない。
例えば「author が Alice で text が Nice article」のコメントを正確に検索することは困難である。
// Lucene では正確なネスト検索が難しい
comments.author:Alice AND comments.text:"Nice article"
このクエリは、Alice のコメントと Bob のコメントが 別々に 条件を満たす場合もヒットしてしまう。
対処法: ネストされたオブジェクトの正確な検索が必要な場合は、Query DSL の nested クエリを使用する。
18.2 スクリプトフィールドの制限
Lucene Query Syntax では、ランタイムフィールド (スクリプトフィールド) に対する直接的な検索はサポートされていない。
// 以下は動作しない
runtime_field:calculated_value
対処法: スクリプトフィールドを使用した検索が必要な場合は、Query DSL の script クエリを使用する。
18.3 集約 (Aggregation) の制限
Lucene Query Syntax 自体には集約機能がない。集約を行うには Query DSL や ES|QL を使用する必要がある。
18.4 パフォーマンスに関する注意事項
| 操作 | パフォーマンス影響 | 推奨事項 |
|---|---|---|
先頭ワイルドカード (*error) | 高い負荷 | 可能な限り避ける |
| 正規表現検索 | 中〜高い負荷 | 範囲を狭めてから使用する |
| あいまい検索 (距離 2) | 中程度の負荷 | 距離 1 で十分な場合は 1 を使用 |
| 大量の OR 条件 | 中程度の負荷 | terms クエリ (Query DSL) を検討 |
| 深いネスト括弧 | 低〜中程度の負荷 | クエリを分割して実行を検討 |
18.5 文字エンコーディングの注意
- Lucene は UTF-8 を前提としている。
- 日本語などのマルチバイト文字は、適切なアナライザー設定が必要。
- CJK (中国語・日本語・韓国語) テキストの検索には、
kuromoji(日本語) やicuアナライザーの設定が推奨される。
18.6 フィールド型による動作の違い
| フィールド型 | フリーテキスト検索 | 完全一致 | 範囲検索 | ワイルドカード |
|---|---|---|---|---|
text | 対応 (アナライズされる) | 困難 | 非対応 | 対応 (トークン単位) |
keyword | 対応 (完全一致) | 対応 | 対応 | 対応 (値全体) |
integer / long | - | 対応 | 対応 | 非対応 |
date | - | 対応 | 対応 | 非対応 |
boolean | - | 対応 | 非対応 | 非対応 |
ip | - | 対応 | 対応 | 制限あり |
19. まとめ
19.1 Lucene Query Syntax の強み
Lucene Query Syntax は Elasticsearch における最も表現力の高い文字列ベースのクエリ言語である。 以下の機能は Lucene でしか利用できない:
- 正規表現検索 (
/pattern/): 複雑なパターンマッチング - あいまい検索 (
word~N): タイポ・スペルミスへの対応 - 近接検索 (
"word1 word2"~N): テキストの近接分析 - ブースティング (
field:value^N): 関連性スコアの制御 - 排他的範囲 (
{min TO max}): 境界値を含まない範囲検索 - +/- 演算子: 柔軟な必須・除外条件
19.2 使い分けの指針
| 状況 | 推奨言語 |
|---|---|
| 日常的なログ検索・フィルタリング | KQL |
| 正規表現・あいまい検索が必要 | Lucene |
| プログラマティックな検索 | Query DSL |
| イベントシーケンス分析 | EQL |
| データの探索・集約 | ES|QL |
19.3 学習のステップ
- まず KQL をマスターする (日常の 80% をカバー)
- KQL の限界を感じたら Lucene を学ぶ
- API 開発やパイプラインでは Query DSL を使う
- セキュリティ分析には EQL を、データ探索には ES|QL を学ぶ
19.4 クイックリファレンス
# フリーテキスト
error
# フィールド指定
status:200
message:"connection refused"
# ブーリアン
status:200 AND extension:php
status:404 OR status:500
NOT status:200
# 必須・除外
+status:200 -extension:css
# 範囲 (閉区間)
status:[400 TO 499]
# 範囲 (開区間)
status:[500 TO *]
# 範囲 (排他)
status:{400 TO 499}
# ワイルドカード
host.name:web-*
status:40?
# 正規表現
message:/[Ee]rror [0-9]+/
# あいまい検索
message:connecton~
message:eror~1
# 近接検索
"database timeout"~3
# ブースティング
title:error^3
# グルーピング
(status:500 OR status:502) AND host.name:prod-*
# エスケープ
message:C\+\+
参考資料:
この記事は AI (Claude) によって生成されました。内容の正確性については公式ドキュメントを参照してください。 Generated: 2026-04-11