elasticsearch-search-relevance について
elastic CLIを使ってElasticsearchの全文検索の関連度を調整するスキルです。コンテンツやカタログのインデックスを管理する人向けに、クエリルールによる固定表示と複数フィールド検索による順位調整を使い分け、変更前後を比較します。
主な機能
- 01インデックスマッピングと検索クエリの確認
- 02クエリルールによる文書の固定・除外
- 03複数フィールド検索による自然順位の調整
- 04変更前後の検索結果の比較
- 05elastic CLI経由の操作
活用シーン
- 01特定クエリで指定商品を先頭に表示
- 02タイトルと説明文の検索順位を改善
- 03複数語クエリの再現率を調査
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ elastic/ agent-skills --skill elasticsearch-search-relevanceインストール後、Claude Code で/elasticsearch-search-relevanceを入力して読み込まれたか確認します。
同梱ファイルreferences/multi-match-tuning.mdreferences/query-rules-reference.md
詳細
Elasticsearch 検索関連性
コンテンツインデックスとカタログインデックスの全文検索結果を改善します。マッピングと現在のクエリを診断し、適切な関連性調整方法(決定的な固定表示にはクエリルール、自然なランキングには multi_match とフィールドブースト)を選択して変更を適用し、上位のヒットを確認してから成功を報告します。
環境設定
このスキルは elastic CLI を使用して Elasticsearch の操作を実行します。
elastic CLI がインストールされていない場合は、何に必要なのかをユーザーに伝えてください。認証情報を推測したり、HTTP API を直接呼び出したり、ほかの回避策を試したりしないでください。
このスキルでは、HTTP 短縮形式(例:GET /、GET /_cat/indices、GET /{index}/_mapping、
GET /{index}/_settings/index.mode、POST /_query)で操作を記載しています。このドキュメントの最後にある
操作テーブルでは、各短縮形式に対応する elastic CLI コマンドを示しています。HTTP API を直接呼び出すのではなく、必ず CLI を使用してください。
対象範囲
このスキルでは、text フィールド(および任意の keyword フィールド)を持つインデックス(商品カタログ、ドキュメント、ナレッジベースなど)の Query DSL 関連性を扱います。評価には POST /{index}/_search を使用し、固定表示または除外するドキュメントにはクエリルール API を使用します。
対象外:
- ES|QL 検索(
POST /_query) —elasticsearch-esqlスキルを使用してください。 - セマンティック検索/ベクトル検索/ハイブリッド検索 — 異なるフィールドタイプとリトリーバーを使用します。
- テキストの関連性を改善するのではなく、価格、日付、人気度で並べ替えること。ただし、ユーザーが明示的に関連性以外の並び順を希望している場合を除きます。
関連性の調整方法
| ユーザーの意図 | 調整方法 | API |
|---|---|---|
| クエリ Q でドキュメント X を常に最初に表示する | クエリルール — pinned ルールと検索時の rule クエリ | PUT /_query_rules/{ruleset_id}, POST /{index}/_search |
| クエリ Q で特定のドキュメントを非表示にする | クエリルール — exclude ルールと rule クエリ | 同上 |
| 自由形式のテキストクエリのランキングを改善する | マッピングされた text フィールドを対象とする multi_match とフィールドブースト | POST /{index}/_search |
| ユーザーの言語に一致しないトークン | Operator、minimum_should_match、または同義語アナライザー | POST /{index}/_search、必要に応じて POST /{index}/_analyze |
判断基準: 特定のクエリで最初に表示する必要のあるドキュメントをユーザーが指定した場合は、クエリルールを使用します。フレーズに対する結果全般の品質が低い場合は、マッピングをもとに自然なクエリを調整します。極端なブースト、function_score、ソート句を使って固定表示を再現しないでください。
手順
-
マッピングと現在のクエリを調べます。
GET /を呼び出して接続を確認します。インデックスが不明な場合は、GET /_cat/indicesで候補を絞り込んでから、GET /{index}/_mappingを呼び出します。マッピングから、すべての
textフィールド(例:title、description)と、フィルターに使用するすべてのkeywordフィールド(brand、category)を列挙します。どのフィールドが短いか(適合率)、長いか(再現率)も確認します。ユーザーが現在の検索ボディを提示している場合は、その内容を読み、どのフィールドを検索しているか、またrule、multi_match、単一フィールドのmatchのいずれをすでに使用しているかを特定します。判断: 問題は決定的な昇格(1 つのクエリで 1 つのドキュメントを必ず上位にすること)ですか、それとも自然なランキング(複数のドキュメントのスコアを改善すること)ですか。必要なデータ: インデックス名、マッピングのプロパティ、現在のクエリ JSON、クエリ文字列の例、固定表示する場合は対象ドキュメント ID。
-
関連性を高める手段を選びます。 手順 1 の判断を適用します。
-
ピン留め/プロモーション →
pinnedタイプのルールを含むクエリルールのルールセットを作成します(プロモーションにexcludeを使ってはいけません)。ルールが意図したクエリテキストに対してのみ発動するようにcriteriaを設定します。たとえば、query_stringのようなメタデータキーに対して、値を"sale"としたcontainsまたはexactを使います。actionsは、ids(例:["SKU123"])またはdocs(例:[{"_index":"catalog","_id":"SKU123"}])で正しいドキュメントをピン留めするように設定します。インデックス間で_idが一意でない可能性がある場合は、docsを使います。完全な構造については、クエリルールリファレンスをお読みください。 -
オーガニックランキング → 長いフィールドに対する単一フィールドの
matchを、マッピングされたtextフィールド全体に対するmulti_matchに置き換えます。短いフィールドをブーストします(通常はtitle^2とし、descriptionはブーストしません)。複数語の再現率が依然として低い場合は、operator、minimum_should_match、または同義語対応のアナライザーを検討します。ただし、テキストの関連性を高く見せるために価格、日付、キーワードフィールドでソートしてはいけません。また、解析対象のユーザーフレーズに対して.keywordサブフィールドをtermでクエリしてはいけません。Multi-Match のチューニングをお読みください。
判断: リクエストごとに、主要な手段を必ず 1 つ選びます。必要なデータ: 選択したフィールドとブースト、ルールセット ID とルール ID の名前、criteria のメタデータキー、ピン留めするドキュメントの識別子。
-
-
変更を適用します。 選択した手段に応じて API を実行します。
クエリルールの手順
PUT /_query_rules/{ruleset_id}でルールセットを作成または置き換えます(または、PUT /_query_rules/{ruleset_id}/_rule/{rule_id}でルールを 1 つ追加します)。GET /_query_rules/{ruleset_id}で構造を確認します。- 検索時に渡すものと同じ
match_criteriaを使い、POST /_query_rules/{ruleset_id}/_testで criteria を検証します。 - 検索に組み込みます:
POST /{index}/_searchでは、ruleset_idがルールセットを参照し、match_criteriaがすべての criteria のmetadataキーに値を指定するruleクエリを使う必要があります(例:"query_string": "sale")。通常の関連性句はorganicの中に配置します。ルールセットを作成しただけでは何もピン留めされません — ピン留めが適用されるのは、検索にruleクエリが含まれている場合のみです。
オーガニックチューニングの手順
- マッピングをもとに、候補となる
multi_match(または同等の bool/should)クエリを作成します。 - トークン化によって結果の欠落を説明できる場合は、サンプルクエリテキストに対して
POST /{index}/_analyzeを実行し、解析結果を確認します(任意)。
判断: 一貫性のある変更セットを 1 つ適用したら、それ以上進めずにテストします。テスト前に無関係な編集を積み重ねないでください。
-
テストし、上位ヒットを比較します。 候補ごとに、変更前と変更後で同じ
size(10 以上)、ユーザーのクエリ文字列、および"track_scores": trueを指定してPOST /{index}/_searchを呼び出します。ピン留めの場合、検索ボディには手順 3 のruleクエリを必ず含めます。各実行について、次の項目を比較します。
- 上位の
_id値と順序 - 関連する場合は
_score - 主な
_sourceフィールド(title、description、商品 ID)
ピン留めの場合、
match_criteriaがクエリに一致すると、対象ドキュメント(例:SKU123)が先頭に表示され、その下にオーガニックな一致結果が表示されることを確認します。オーガニックチューニングの場合、ソートやキーワードの完全一致を利用した小細工に頼らず、タイトルと意図に合ったドキュメントの順位が上がることを確認します。判断: エビデンスに基づいて最良の候補を採用します。どの候補も結果を改善しない場合は、試した内容を報告し、次の手段(同義語やフィールドの追加など)を提案します。必要なデータ: ベースラインクエリと候補クエリの上位ヒットリストを並べた比較。
- 上位の
例
catalog でクエリ「sale」に対して SKU123 をピン留めする
誤り: SKU123 をブーストする、_id でソートする、または rule 検索クエリを指定せずにルールセットを作成する。
正しい方法:
pinnedルールを含むPUT /_query_rules/catalog-sale-pinを実行します。criteria はクエリテキスト"sale"に一致させ、actions はSKU123をピン留めします。- 次の内容で
POST /catalog/_searchを実行します。
{
"query": {
"rule": {
"ruleset_id": "catalog-sale-pin",
"match_criteria": { "query_string": "sale" },
"organic": {
"multi_match": {
"query": "sale",
"fields": ["title^2", "description"]
}
}
}
},
"size": 10
}
SKU123 が 1 件目にヒットし、残りのヒットがピン留めされた結果の下にオーガニックな一致結果として表示されることを確認します。
description のみが検索される場合に「running shoes」を改善する
マッピングでは、title と description は text、brand と category は keyword として定義されています。
誤り: description のみを対象とする match を維持し、価格順に並べ替え、title.keyword に対して term クエリを使用します。
正しい方法:
- ベースライン:ユーザーが現在使用している
descriptionに対するmatchを使ってPOST /catalog/_searchを実行し、上位のヒットを記録します。 - 候補:次の内容で
POST /catalog/_searchを実行します。
{
"query": {
"multi_match": {
"query": "running shoes",
"fields": ["title^2", "description"],
"type": "best_fields",
"operator": "or",
"minimum_should_match": "75%"
}
},
"size": 10
}
- 上位のヒットを比較します。
titleに「running shoes」を含むドキュメントは、descriptionのみに一致するドキュメントより上位に表示されるはずです。それでも再現率が低い場合は、後続のイテレーションで同義語の展開を検討します(価格順への並べ替えではありません)。
ガイドライン
- すべてのフィールド名をマッピングに基づいて指定する —
GET /{index}/_mappingを確認せずに、name、content、bodyを決して作り出さないでください。 - ピン留めにはクエリルール、ランキングにはブースト — マーチャンダイジングはクエリルールで行い、フィールドのブーストはオーガニック検索クエリで行います。
- マッチ条件の連携は必須 — ルール条件の
metadataキーは、実行時の値(通常はユーザーのクエリ文字列)とともに、検索のrule.match_criteriaオブジェクトに含める必要があります。 - 成功を主張する前にテストする — ベースライン検索と候補検索を実行し、上位ヒットの変化を示します。
keywordフィールドはフィルタリング、textフィールドは検索に使う — 自然言語の主な全文検索対象としてではなく、filterコンテキストでkeywordフィールドを使用します。- 必ず具体的な成果物を提供する — 検証のためにクラスターへ接続できない場合でも、完全なルールセット JSON(ピン留め用)または候補クエリ本文(オーガニック検索の調整用)を作成し、接続が利用可能になった後の検証方法を説明します。概要だけで終わらせないでください。
参考資料
- クエリルールのリファレンス — 条件の種類、
pinnedアクション、ルールセット JSON、ruleクエリの連携、テスト API - マルチマッチの調整 — フィールドブースト、演算子、テストの規律、アンチパターン
操作
| HTTP API(省略形) | elastic CLI コマンド |
|---|---|
GET / | elastic es info |
GET /_cat/indices | elastic es cat indices --index '<pattern>' |
GET /{index}/_mapping | elastic es indices get-mapping --index '<index>' |
PUT /_query_rules/{ruleset_id} | elastic es query-rules put-ruleset --ruleset-id '<id>' --rules '<json>' |
PUT /_query_rules/{ruleset_id}/_rule/{rule_id} | elastic es query-rules put-rule --ruleset-id '<id>' --rule-id '<id>' --type pinned --criteria '<json>' --actions '<json>' |
GET /_query_rules/{ruleset_id} | elastic es query-rules get-ruleset --ruleset-id '<id>' |
POST /_query_rules/{ruleset_id}/_test | elastic es query-rules test --ruleset-id '<id>' --match-criteria '<json>' |
POST /{index}/_search | elastic es search --index '<index>' --query '<json>' |
POST /{index}/_analyze | elastic es indices analyze --index '<index>' --field '<field>' --text '<text>' |