次の方法で共有


Azure AI 検索で検索結果を整形するか検索結果の構成を変更する

この記事では、検索結果の構成と、シナリオに合わせて検索結果を整形する方法について説明します。 検索結果はクエリ応答で返されます。 応答の形状は、クエリ自体のパラメーターによって決まります。 これらのパラメーターには、以下のものがあります。

  • インデックスで見つかった一致の数 (count)
  • 応答で返される一致の数 (既定では 50、top で構成可能) またはページごと (skiptop)
  • ランク付けに使用される各結果の検索スコア (@search.score)
  • 検索結果に含まれるフィールド (select)
  • 並べ替えロジック (orderby)
  • 結果内の用語を強調表示し、本文内の用語の全体または一部に一致します
  • セマンティック ランカーからのオプションの要素 (一番上に answers、各一致に captions)

検索結果には最上位レベルのフィールドが含まれる場合がありますが、応答のほとんどは配列内の一致するドキュメントで構成されます。

クエリ応答を定義するためのクライアントと API

次のクライアントを使用してクエリ応答を構成できます。

結果の構成

結果は主に表形式で、すべて retrievable フィールドか、select パラメーターで指定されたフィールドのみに制限されたフィールドのいずれかで構成されます。 行は一致するドキュメントであり、クエリ ロジックで関連性のランク付けが除外されない限り、通常、関連性の順序でランク付けされます。

検索結果に含まれるフィールドを選択できます。 検索ドキュメントには多数のフィールドが含まれる可能性がありますが、一般に、結果セット内の各ドキュメントを表すために必要なものは数個しかありません。 クエリ要求で、select=<field list> を追加して、応答にどの retrievable フィールドを表示するかを指定します。

各ドキュメントを比較対照して区別するフィールドを選択することにより、ユーザーの側にクリックスルー応答を誘うための十分な情報を提供するフィールドが含まれます。 eコマース サイトでは、それは製品名、説明、ブランド、色、サイズ、価格、評価などである場合があります。 組み込みの hotels-sample インデックスの場合、次の例の "select" フィールドのようになります。

POST /indexes/hotels-sample-index/docs/search?api-version=2024-07-01 
    {  
      "search": "sandy beaches",
      "select": "HotelId, HotelName, Description, Rating, Address/City",
      "count": true
    }

予期しない結果が生じた場合のヒント

場合によっては、クエリの出力が期待している内容でないこともあります。 たとえば、一部の結果が重複しているように見える場合や、上部の近くに表示され "なければならない" 結果が下の方に配置される場合があります。 クエリの結果が予期しないものである場合は、こちらのクエリ変更を試して、結果が改善されるかどうかを確認できます。

  • searchMode=any (既定) を searchMode=all に変更し、いずれかの条件への一致ではなく、すべての条件への一致を強制します。 これは特に、ブール演算子がクエリに含まれているときに当てはまります。

  • さまざまな字句アナライザーやカスタム アナライザーを試して、クエリ結果が変わるかどうかを確認します。 既定のアナライザーでは、ハイフンでつながれた単語を分割し、単語を原形に変換します。通常はこれにより、クエリ応答の堅牢性が向上します。 ただし、ハイフンを保持する必要がある場合、または文字列に特殊文字が含まれている場合は、インデックスに適切な形式のトークンが含まれるようにカスタム アナライザーを構成することが必要になる場合があります。 詳細については、「部分的な用語検索と特殊文字を含むパターン (ハイフン、ワイルドカード、正規表現、パターン)」を参照してください。

一致のカウント

count パラメーターは、クエリに一致すると見なされるインデックス内のドキュメントの数を返します。 カウントを返すには、クエリ要求に count=true を追加します。 検索サービスによって課される最大値はありません。 クエリおよびドキュメントの内容によっては、カウントがインデックス内のすべてのドキュメントと同じ大きさになる場合があります。

インデックスが安定している場合、カウントは正確です。 システムがドキュメントをアクティブに追加、更新、または削除している場合、インデックスが完全に作成されていないドキュメントを除き、カウントは概算値になります。

Count は、定期的なメンテナンスや検索サービスのその他のワークロードの影響を受けません。 ただし、複数のパーティションと 1 つのレプリカがある場合は、パーティションの再起動時にドキュメント数 (数分) に短期的な変動が発生する可能性があります。

ヒント

インデックス作成操作をチェックするには、空の検索 search=* クエリに count=true を追加することで、インデックスに予想される数のドキュメントが含まれているかどうかを確認できます。 結果は、インデックス内のドキュメントの完全な数になります。

クエリ構文をテストするとき、count=true は、変更によって返される結果が多いか少ないかをすばやく判断できるため、有用なフィードバックになります。

応答の結果の数

Azure AI 検索は、サーバー側のページングを使用して、クエリが一度に大量のドキュメントを取得しないようにします。 応答内の結果の数を決定するクエリ パラメーターは、topskip です。 top は、ページ内の検索結果の数を指します。 skiptop の間隔であり、次のセットを取得する前にスキップする結果の数を検索エンジンに指示します。

既定のページ サイズは 50 ですが、最大ページ サイズは 1,000 です。 1,000 より大きい値を指定し、インデックスで 1,000 を超える結果が見つかった場合、最初の 1,000 件の結果のみが返されます。 一致する数がページ サイズを超える場合、応答には結果の次のページを取得するための情報が含まれます。 次に例を示します。

"@odata.nextLink": "https://contoso-search-eastus.search.windows.net/indexes/realestate-us-sample-index/docs/search?api-version=2024-07-01"

クエリが全文検索またはセマンティックであると想定して、上位一致は検索スコアによって決定されます。 それ以外の場合、上位一致は完全一致クエリの任意の順序になります (一律の @search.score=1.0 は任意のランク付けを示します)。

既定値の 50 をオーバーライドするには、top を設定します。 新しいプレビュー API では、ハイブリッド クエリを使用すれば、maxTextRecallSize を指定し、最大 10,000 件のドキュメントを返すことができます。

結果セットで返されるすべてのドキュメントのページングを制御するには、topskip を一緒に使用します。 このクエリは、一致するドキュメントの最初のセット 15 件と、合計一致件数を返します。

POST https://contoso-search-eastus.search.windows.net/indexes/realestate-us-sample-index/docs/search?api-version=2024-07-01

{
    "search": "condos with a view",
    "count": true,
    "top": 15,
    "skip": 0
}

このクエリは、最初の 15 件をスキップして次の 15 件 (16 から 30) を取得して、2 番目のセットを返します。

POST https://contoso-search-eastus.search.windows.net/indexes/realestate-us-sample-index/docs/search?api-version=2024-07-01

{
    "search": "condos with a view",
    "count": true,
    "top": 15,
    "skip": 15
}

基になるインデックスが変更されている場合、ページ分割されたクエリの結果の安定性は保証されません。 ページングによって各ページの skip の値が変更されますが、各クエリは独立しており、クエリ時にインデックス内に存在する (つまり、汎用データベースで見られるような結果のキャッシュやスナップショットは存在しない) ため、データの現在のビューに対して動作します。

次の例は、重複がどのように発生するかを示しています。 4 つのドキュメントを含む次のインデックスがあるとします。

{ "id": "1", "rating": 5 }
{ "id": "2", "rating": 3 }
{ "id": "3", "rating": 2 }
{ "id": "4", "rating": 1 }

ここでは、結果を一度に 2 つ、評価の順序で返してもらいたいとします。 結果の最初のページを取得するために $top=2&$skip=0&$orderby=rating desc というクエリを実行すると、次の結果が生成されます。

{ "id": "1", "rating": 5 }
{ "id": "2", "rating": 3 }

このサービスでは、クエリ呼び出しの間に { "id": "5", "rating": 4 } という 5 番目のドキュメントがインデックスに追加されたとします。 その後すぐに、2 ページ目をフェッチするために $top=2&$skip=2&$orderby=rating desc というクエリを実行すると、次の結果が得られます。

{ "id": "2", "rating": 3 }
{ "id": "3", "rating": 2 }

ドキュメント 2 が 2 回フェッチされることに注意してください。 これは、新しいドキュメント 5 の方が評価の値が大きいため、ドキュメント 2 の前に並べ替えられ、最初のページに割り当てられるためです。 この動作は予期されない可能性がありますが、検索エンジンの動作としては一般的なものです。

多数の結果をページングする

ページングの別の手法は、skip の回避策として、並べ替え順序範囲フィルターを使用することです。

この回避策では、並べ替えとフィルターは、ドキュメント ID フィールドかドキュメントごとに一意となる別のフィールドに適用されます。 一意のフィールドの検索インデックスには filterable および sortable 属性が必要です。

  1. 並べ替えられた結果の完全なページを返すクエリを発行します。

    POST /indexes/good-books/docs/search?api-version=2024-07-01
        {  
          "search": "divine secrets",
          "top": 50,
          "orderby": "id asc"
        }
    
  2. 検索クエリによって返された最後の結果を選択します。 ID 値のみの結果例をここに示します。

    {
        "id": "50"
    }
    
  3. 範囲クエリでその ID 値を使用し、結果の次のページをフェッチします。 この ID フィールドには一意の値が必要です。それがない場合、改ページ位置の自動修正に重複する結果が含まれる可能性があります。

    POST /indexes/good-books/docs/search?api-version=2024-07-01
        {  
          "search": "divine secrets",
          "top": 50,
          "orderby": "id asc",
          "filter": "id ge 50"
        }
    
  4. クエリから 0 個の結果が返されると、改ページ位置の自動修正が終了します。

Note

filterable および sortable 属性は、フィールドが最初にインデックスに追加されたときにのみ有効にできます。既存のフィールドには有効にできません。

順番の結果

フルテキスト検索クエリでは、結果は次の基準でランク付けできます。

  • 検索スコア
  • セマンティック再ランカー スコア
  • sortable フィールドの並べ替え順序

スコアリング プロファイルを追加することで、特定のフィールドで見つかった一致をブーストすることもできます。

検索スコアによる並べ替え

フルテキスト検索クエリの場合、結果は BM25 アルゴリズムを使用して、用語の出現頻度、ドキュメントの長さ、ドキュメントの平均長に基づいて計算され、自動的に検索スコアによってランク付けされます

@search.score の範囲は無制限か、以前のサービスでは 0 から 1.00 まで (ただし 1.00 は含まず) のいずれかです。

いずれのアルゴリズムの場合でも、@search.score が 1.00 の場合は、スコアなしまたはランク付けのない結果セットを示し、すべての結果に対してスコアは一律に 1.0 になります。 スコア付けされていない結果が発生するのは、クエリ フォームがあいまい検索、ワイルドカードまたは正規表現のクエリ、または空の検索 (search=*) である場合です。 スコア付けされていない結果に対してランク付け構造を設定する必要がある場合は、その目標を達成するため、orderby 式を検討してください。

セマンティック再ランカーによる並べ替え

セマンティック ランカーを使用している場合は、結果の並べ替え順序は @search.rerankerScore によって決まります。

@search.rerankerScore の範囲は 1 から 4.00 で、スコアが高いほどセマンティック一致が強いことを示します。

orderby を使用した並べ替え

一貫した順序付けがアプリケーションの要件である場合は、フィールドに対して orderbyを定義できます。 「並べ替え可能」としてインデックス付けされたフィールドのみを使用して、結果を並べ替えることができます。

orderby でよく使用されるフィールドとしては、評価、日付、場所などがあります。 場所によるフィルター処理では、フィールド名に加えて、フィルター式で geo.distance() 関数を呼び出す必要があります。

数値フィールド (Edm.DoubleEdm.Int32Edm.Int64) は、数値の順序 (1、2、10、11、20 など) で並べ替えられます。

文字列フィールド (Edm.StringEdm.ComplexType サブフィールド) は、言語に応じて、ASCII 並べ替え順序または Unicode 並べ替え順序で並べ替えられます。

  • 文字列フィールドの数値の内容は、アルファベット順に並べ替えられます (1、10、11、2、20)。

  • 大文字の文字列の方が小文字より前になります (APPLE、Apple、BANANA、Banana、apple、banana)。 テキスト ノーマライザーを割り当てて並べ替えの前にテキストを前処理し、この動作を変更することができます。 Azure AI 検索の並べ替えはフィールドの分析されていないコピーに対して行われるため、フィールドで小文字トークナイザーを使用しても、並べ替え動作には影響しません。

  • 分音記号が前にある文字列は最後に表示されます (Äpfel、Öffnen、Üben)

スコアリング プロファイルを使用して関連性をブーストする

順序の一貫性を高める別の方法として、カスタム スコアリング プロファイルを使用する方法があります。 スコアリング プロファイルを使用すると、検索結果内の項目のランク付けをより細かく制御できるため、特定のフィールドで見つかる一致を向上させることができます。 追加のスコアリング ロジックにより、各ドキュメントの検索スコアがさらに離れるため、レプリカ間のわずかな違いのオーバーライドに役立ちます。 このアプローチにはランク付けアルゴリズムをお勧めします。

検索結果の強調表示

検索結果の強調表示とは、結果内の一致する用語に適用され、一致が容易に見つかるようにするテキストの書式設定 (太字や黄色の強調表示など) を指します。 強調表示は、説明フィールドなど、一致が一目ではわかりにくい、長いコンテンツ フィールドに対して便利です。

強調表示は個々の用語に適用されることに注意してください。 フィールド全体の内容を強調表示する機能はありません。 フレーズを強調する場合は、引用符で囲まれたクエリ文字列で一致する用語 (またはフレーズ) を指定する必要があります。 この手法については、このセクションで詳しく説明します。

検索結果の強調表示の手順については、クエリ要求に関する記事で説明しています。 エンジンのクエリ拡張をトリガーするクエリ (あいまい検索やワイルドカード検索など) では、検索結果の強調表示のサポートが制限されています。

ヒットの強調表示の要件

  • フィールドは Edm.String または Collection(Edm.String) にする必要があります。
  • フィールドは searchable 属性を持つ必要があります

要求で強調表示を指定する

強調表示された用語を返すには、クエリ要求に highlight パラメーターを含めます。 このパラメーターには、コンマ区切りのフィールド リストを設定します。

既定では、形式のマークアップは <em> ですが、highlightPreTaghighlightPostTag パラメーターを使用してタグをオーバーライドできます。 クライアントのコードで応答を処理します (たとえば、太字のフォントや黄色の背景の適用)。

POST /indexes/good-books/docs/search?api-version=2024-07-01
    {  
      "search": "divine secrets",  
      "highlight": "title, original_title",
      "highlightPreTag": "<b>",
      "highlightPostTag": "</b>"
    }

既定では、Azure AI Search によって、フィールドごとに最大 5 つの強調表示が返されます。 ダッシュとそれに続く整数を追加することで、この値を調整できます。 たとえば、"highlight": "description-10" とすると、description フィールドで一致するコンテンツについて、10 個まで強調表示された用語が返されます。

強調表示された結果

強調表示がクエリに追加されると、アプリケーションのコードでその構造をターゲットにできるように、応答の結果ごとに @search.highlights が含まれます。 "highlight" で指定されたフィールドのリストが応答に含まれます。

キーワード検索では、各用語が個別にスキャンされます。 "divine secrets" のクエリからは、いずれかの用語を含むすべてのドキュメントでの一致が返されます。

語句クエリに対する強調表示のスクリーンショット。

キーワード検索の強調表示

強調表示されたフィールド内では、すべての用語に書式が適用されます。 たとえば、"The Divine Secrets of the Ya-Ya Sisterhood" に対する一致では、それらが連続している場合でも、各用語に個別に書式設定が適用されます。

"@odata.count": 39,
"value": [
    {
        "@search.score": 19.593246,
        "@search.highlights": {
            "original_title": [
                "<em>Divine</em> <em>Secrets</em> of the Ya-Ya Sisterhood"
            ],
            "title": [
                "<em>Divine</em> <em>Secrets</em> of the Ya-Ya Sisterhood"
            ]
        },
        "original_title": "Divine Secrets of the Ya-Ya Sisterhood",
        "title": "Divine Secrets of the Ya-Ya Sisterhood"
    },
    {
        "@search.score": 12.779835,
        "@search.highlights": {
            "original_title": [
                "<em>Divine</em> Madness"
            ],
            "title": [
                "<em>Divine</em> Madness (Cherub, #5)"
            ]
        },
        "original_title": "Divine Madness",
        "title": "Divine Madness (Cherub, #5)"
    },
    {
        "@search.score": 12.62534,
        "@search.highlights": {
            "original_title": [
                "Grave <em>Secrets</em>"
            ],
            "title": [
                "Grave <em>Secrets</em> (Temperance Brennan, #5)"
            ]
        },
        "original_title": "Grave Secrets",
        "title": "Grave Secrets (Temperance Brennan, #5)"
    }
]

語句検索の強調表示

複数の用語が二重引用符で囲まれている語句検索であっても、語句全体の書式設定が適用されます。 次の例は同じクエリですが、"divine search" が引用符で囲まれた語句として送信されている点が異なります (一部の REST クライアントでは、内部の引用符をバックスラッシュ \" でエスケープする必要があります)。

POST /indexes/good-books/docs/search?api-version=2024-07-01 
    {  
      "search": "\"divine secrets\"",
      "select": "title,original_title",
      "highlight": "title",
      "highlightPreTag": "<b>",
      "highlightPostTag": "</b>",
      "count": true
    }

条件で両方の用語が与えられているため、検索インデックスで一致するのは 1 つだけです。 前のクエリに対する応答は次のようになります。

{
    "@odata.count": 1,
    "value": [
        {
            "@search.score": 19.593246,
            "@search.highlights": {
                "title": [
                    "<b>Divine</b> <b>Secrets</b> of the Ya-Ya Sisterhood"
                ]
            },
            "original_title": "Divine Secrets of the Ya-Ya Sisterhood",
            "title": "Divine Secrets of the Ya-Ya Sisterhood"
        }
    ]
}

古いサービスでの語句の強調表示

2020 年 7 月 15 日より前に作成された検索サービスでは、語句クエリに対して異なる強調表示エクスペリエンスが実装されています。

次の例では、引用符で囲まれた語句 "super bowl" を含むクエリ文字列が想定されています。 2020 年 7 月より前は、語句内のすべての用語が強調表示されます。

"@search.highlights": {
    "sentence": [
        "The <em>super</em> <em>bowl</em> is <em>super</em> awesome with a <em>bowl</em> of chips"
   ]

2020 年 7 月以降に作成された検索サービスの場合、フル フレーズ クエリに一致する語句のみが @search.highlights で返されます。

"@search.highlights": {
    "sentence": [
        "The <em>super</em> <em>bowl</em> is super awesome with a bowl of chips"
   ]

次のステップ

クライアントの検索ページをすばやく生成するには、次のオプションを検討してください。

  • Azure portal の [デモ アプリの作成] では、検索バー、ファセット ナビゲーション、画像がある場合はサムネイル領域を備えた HTML ページを作成します。

  • ASP.NET Core (MVC) アプリに検索を追加する方法に関するページは、機能するクライアントを構築するチュートリアルとコード サンプルです。

  • Web アプリに検索を追加する」は、ユーザー エクスペリエンスに React JavaScript ライブラリを使用する C# のチュートリアルとコード サンプルです。 アプリは Azure Static Web Apps を使用して配置され、改ページ位置の自動修正を実装します。