パターンマッチング
エージェント型検索アプリケーションでは、ベクトル検索とgrepスタイルのパターンマッチングが互いに補完し合うことがよくあります。ベクトル検索は意味的に関連性の高いエンティティを検索し、パターンマッチングはエラーコード、ログのプレフィックス、メールドメイン、URLパス、識別子などの正確な文字列構造に基づいて、それらの検索結果を絞り込みます。
Milvusでは、これらのパターン制約をスカラーフィルターで表現できます。単純なワイルドカードマッチングにはLIKE を、RE2正規表現には=~ または!~ を使用します。これらのフィルターは、query 、search 、またはハイブリッド検索と組み合わせることができます。
このページでは、query 、search 、およびハイブリッド検索で使用されるスカラーフィルタ式におけるパターンマッチングについて説明します。これらの式はフィールド値を評価するものであり、アナライザによって生成されたトークンを変更することはありません。テキスト解析中にトークンをフィルタリングするには、「Regex Analyzer Filter」を参照してください。
パターンマッチング式は、filter パラメータ内で記述します。たとえば、次のクエリは、E1001 などのエラーコードを含むログメッセージに一致します。
from pymilvus import MilvusClient
client = MilvusClient(uri="http://localhost:19530")
res = client.query(
collection_name="log_events",
filter='message =~ "E[0-9]{4}"',
output_fields=["message", "severity"],
)
このページの例では、filter に割り当てられた式に焦点を当てています。query 、search 、ハイブリッド検索など、スカラーフィルターを受け入れるMilvus操作では、同じフィルター式構文を使用できます。
サポートされているフィールド型
パターンマッチングは、文字列値に対して利用可能です。
| 対象 | LIKE | 正規表現=~ /!~ | 注 |
|---|---|---|---|
VARCHAR フィールド | はい | はい | 文字列フィールドでのパターンマッチングの一般的な対象。 |
JSON VARCHAR 型にキャストされたパス | はい | はい | JSON パスの値は、正の一致を得るためには文字列でなければなりません。高速化のために JSON パスにインデックスを作成する場合は、json_cast_type="varchar" を設定してください。 |
ARRAY<VARCHAR> element | はい | はい | tags[0] など、インデックスによって特定の要素に一致させます。パターンマッチングはすべての要素をスキャンするわけではなく、指定されたインデックスの要素にのみ適用されます。 |
数値、ブール値、ベクトル、TEXT 、またはその他の非VARCHAR ターゲット | いいえ | いいえ | パターンマッチングは、VARCHAR 値、文字列に解決される JSON パス、またはインデックス付きARRAY<VARCHAR> 要素でのみ使用できます。 |
LIKE または正規表現を選択してください
必要なパターンを表現できる最も単純な演算子を選択してください。
文字列の完全一致が必要な場合は、パターンマッチングの代わりに `== ` を使用することをお勧めします。`LIKE ` または正規表現は、フィルタがパターンに一致する必要がある場合にのみ使用してください。
| 要件 | 推奨される演算子 | 例 | 説明 |
|---|---|---|---|
| 文字列の完全一致 | == | status == "active" | 文字列「active 」との完全一致。 |
| 単純な接頭辞一致 | LIKE | name LIKE "Prod%" | 「Prod 」で始まる文字列に一致します。 |
| 単純なサフィックス一致 | LIKE | filename LIKE "%.json" | .json で終わる文字列に一致します。 |
| 単純な部分一致 | LIKE | description LIKE "%vector database%" | 文字列内のどこかにvector database が含まれる値に一致します。 |
| 構造化されたコードまたは固定長のパターンに一致させる | =~ | code =~ "E[0-9]{4}" | 大文字と小文字を区別して、E の後に 4 桁の数字が続く文字列(例:E1001 )に一致します。 |
| 大文字小文字を区別しないパターン一致 | =~ で(?i) | message =~ "(?i)error" | error 、ERROR 、またはその他の大文字小文字のバリエーションに一致します。 |
| 正規表現パターンに一致する値を除外する | !~ | message !~ "^DEBUG" | DEBUG で始まる文字列を除外します。 |
単純なワイルドカード一致には「LIKE 」を使用します。パターンに文字クラス、繰り返し、error|failed などの選択、アンカー、または大文字小文字を区別しない一致が必要な場合は、正規表現を使用します。
LIKEの使用
LIKE 演算子は、文字列値に対する単純なワイルドカード一致に使用します。以下のワイルドカードのみをサポートしています:
| ワイルドカード | 説明 |
|---|---|
% | 0個以上の文字に一致します。 |
_ | 1文字に正確に一致します。 |
一般的な LIKE パターン
% および_ の位置を使用して、一致した文字列内のどこに固定テキストが表示されるかを制御します。
| 要件 | パターン | フィルタの例 |
|---|---|---|
| プレフィックスで始まる | Prod% | filter = 'name LIKE "Prod%"' |
| 接尾辞で終わる | %.json | filter = 'filename LIKE "%.json"' |
| 部分文字列を含む | %vector% | filter = 'description LIKE "%vector%"' |
| 固定位置の1文字に一致 | AB_% | filter = 'code LIKE "AB_%"' |
LIKE の一致動作
接頭辞、接尾辞、部分文字列の包含、および固定位置の単一文字の一致には、LIKE を使用してください。LIKE は、[0-9] のような文字クラス、error|failed のような選択、{4} のような繰り返し回数、^ や$ のようなアンカー、(?i) のような大文字小文字を区別しないフラグをサポートしていません。これらのパターンには、regex を使用してください。
文字列全体が完全に一致する場合は、== を使用してください。LIKE は、フィルタでワイルドカードマッチングが必要な場合にのみ使用してください。
LIKE パターンにおけるワイルドカードのエスケープ
LIKE パターンでは、% は 0 個以上の文字に一致し、_ は正確に 1 文字に一致します。% 、_ 、または\ をリテラルとして一致させるには、バックスラッシュ (\) で文字をエスケープします:
name LIKE r"\%"リテラル値「%」に一致します。name LIKE r"\_%"リテラル「_」で始まる値に一致します。name LIKE r"\\%"リテラルなバックスラッシュで始まる値に一致します。
r"..." やr'...' のように記述される生文字列リテラルは、Milvus のフィルター式においてバックスラッシュをそのまま保持します。これらは、LIKE や、バックスラッシュを含む正規表現パターンに推奨されます。生文字列を使用しない場合、通常の文字列リテラルはパターンが評価される前にエスケープシーケンスを処理するため、より多くのバックスラッシュが必要になる可能性があります。
正規表現の使用Compatible with Milvus 3.0.x
パターンに文字クラス、反復、選択、アンカー、大文字小文字を区別しないマッチングなどの正規表現機能が必要な場合は、正規表現フィルターを使用してください。Milvusは、文字列値に対してRE2正規表現を適用します。
=~ または!~ の右辺は、文字列リテラルでなければなりません。
| 演算子 | 意味 | 例 |
|---|---|---|
=~ | 正規表現パターンに一致する値にマッチします。 | filter = 'message =~ "E[0-9]{4}"' |
!~ | 正規表現パターンに一致する値を除外します。 | filter = 'message !~ "^DEBUG"' |
生の文字列リテラルを使用する
バックスラッシュを含む正規表現パターンには、生の文字列リテラルを使用することを推奨します。r"..." やr'...' のように記述された生の文字列では、バックスラッシュがそのまま正規表現エンジンに渡されます。これにより、通常の文字列リテラルで必要となる追加のエスケープ処理が不要になります。
例:
filter = 'message =~ r"\d{4}-\d{2}-\d{2}"'
これは、2026-07-01 のような日付形式の値を含む文字列に一致します。
生の文字列を使用しない場合、通常の文字列リテラルでは正規表現パターンが評価される前にエスケープシーケンスが処理されるため、\d や\s といったパターン、あるいはエスケープされたリテラル文字には、追加のバックスラッシュが必要になる場合があります。
一般的な正規表現パターン
以下の例では、Milvus のフィルター式で一般的に使用される RE2 構文を使用しています。正規表現の完全な構文については、RE2 構文リファレンスを参照してください。
| 要件 | パターン | フィルタの例 |
|---|---|---|
| リテラルテキストを含む | error | filter = 'message =~ "error"' |
| プレフィックスで始まる | ^ERR | filter = 'code =~ "^ERR"' |
| 接尾辞で終わる | \.json$ | filter = 'filename =~ "\\.json$"' |
| 数字の連続に一致 | [0-9]+ | filter = 'message =~ "[0-9]+"' |
| 固定された桁数の数字に一致 | [0-9]{4} | filter = 'code =~ "[0-9]{4}"' |
| メールアドレスのドメインに一致する | @example\.com$ | filter = 'email =~ "@example\\.com$"' |
| 大文字小文字を区別せずに一致 | (?i)error | filter = 'message =~ "(?i)error"' |
| 文字列全体に一致する | ^prod-[0-9]+$ | filter = 'name =~ "^prod-[0-9]+$"' |
複数の単語のうちいずれか1つに一致させるには、| を使用した選択(alternation)を利用します:
filter = 'message =~ "error|failed|timeout"'
正規表現のメタ文字をリテラルとして一致させる場合は、正規表現パターン内でエスケープしてください。たとえば、リテラルとしてのドット(正規表現では `\. `)に一致させるには、Python フィルター文字列で `\\. ` と記述します:
filter = 'email =~ "@gmail\\.com$"'
注:Milvusの正規表現フィルターはRE2構文に従います。正規表現パターンがRE2でサポートされていない構文を使用している場合、またはその他の理由で無効な場合、Milvusはそのフィルター式を拒否します。正規表現のメタ文字、フラグ、およびマッチング動作の詳細については、RE2構文リファレンスを参照してください。
マッチングの挙動
部分文字列の一致
Milvus の正規表現マッチングでは、部分文字列のセマンティクスが使用されます。パターンはフィールド値全体と一致する必要はありません。たとえば、次のフィルターはE1001 とfailed with E1001 after retry の両方に一致します:
filter = 'message =~ "E[0-9]{4}"'
フィールド値全体に一致させるには、^ および$ というアンカーを使用します:
# Match only values that are exactly E followed by four digits
filter = 'code =~ "^E[0-9]{4}$"'
NULL 許容の VARCHAR フィールド
正規表現フィルターはNULL値には一致しません。これは、=~ および!~ の両方に適用されます。正規表現パターンを除外しつつNULL値は保持したい場合は、明示的にOR field IS NULL を追加してください:
filter = 'message !~ "^DEBUG" OR message IS NULL'
JSONパス
JSONパスについては、パスが欠落している場合、nullの場合、または文字列以外の値に解決される場合、正規表現フィルターの動作が異なります:
| フィルタ | 欠落値/null値/文字列以外の値を含みますか? | 備考 |
|---|---|---|
json_field["path"] =~ "pattern" | いいえ | 正規表現のパターンに一致する文字列値のみをマッチさせます。 |
json_field["path"] !~ "pattern" | はい | パスが欠落している、null、文字列以外、または正規表現パターンに一致しない文字列であるエンティティを返します。 |
インデックスを使用したパターンマッチングの高速化
Milvus は、文字列フィールドに対して、LIKE や、VARCHAR フィールドまたは JSON 文字列パスに対する正規表現フィルターと組み合わせて使用できる、いくつかのインデックスタイプをサポートしています。例としては、NGRAM 、STL_SORT 、INVERTED 、BITMAP などがあります。パターンマッチングはインデックスなしでも機能しますが、インデックスを使用することで、大規模なデータセットでのパフォーマンスを向上させることができます。
インデックスの有効性は、パターン式、Milvusが固定のリテラル部分文字列を抽出できるかどうか、および対象フィールドのカーディナリティと分布によって異なります。name LIKE "Prod%" のようなプレフィックス形式のパターンは、description LIKE "%vector%" やfilename LIKE "%.json" のようなインフィックスやサフィックス形式のパターンとは異なるインデックス戦略を採用することで、パフォーマンス向上が期待できる場合があります。
以下の表を参考として、実際のワークロードでベンチマークテストを行ってください:
| パターンまたはデータの特性 | 検討すべきインデックス | 備考 |
|---|---|---|
message =~ "error.*timeout" のような固定のリテラル部分文字列を含む場合、またはmessage LIKE "%database%" | NGRAM | Milvus がパターンから意味のあるリテラル部分文字列を抽出できる場合に有効です。詳細については、NGRAM を参照してください。 |
| プレフィックス、完全一致、または等価のような文字列フィルター。特に、カーディナリティが低~中程度のフィールドで有効 | STL_SORT、INVERTED 、またはBITMAP | フィールドに重複する値がある場合や、フィルタが完全一致に近い場合に、より効果的である可能性があります。詳細については、STL_SORT、INVERTED、およびBITMAPを参照してください。 |
| 固定リテラルを含まない正規表現パターン、または文字クラス、短いトークン、ワイルドカードが主体となるパターン | インデックスによる高速化を頼りにする前にベンチマークを実行してください | これらのパターンは、インデックスによる選択性が限定的となり、より広範囲なスキャンに切り替わってしまう可能性があります。 |