次の方法で共有


Azure AI 検索の "単純" 検索クエリの例

Azure AI Search では、単純なクエリ構文、フルテキスト検索用のデフォルトのクエリ パーサーを呼び出します。 このパーサーは高速で、フルテキスト検索、フィルター検索、ファセット検索、プレフィックス検索などの一般的なシナリオに対応します。 この記事では、例を使用して、ドキュメントの検索 (REST API) 要求での単純な構文の使用方法を示します。

Note

代替のクエリ構文は Lucene であり、あいまい検索、ワイルドカード検索などのより複雑なクエリ構造をサポートしています。 詳細については、「"完全な" Lucene 検索構文の例」を参照してください。

ホテルのサンプル インデックス

以下のクエリは、「クイックスタート: Azure portal で検索インデックスを作成する」の手順に従って作成できる hotels-sample-index に基づいています。

クエリの例は、REST API および POST 要求を使用して表されています。 これらは REST クライアントに貼り付けて実行できます。 または、Azure portal で検索エクスプローラーの JSON ビューを使用してください。 JSON ビューでは、この記事でここに示すクエリの例に貼り付けることができます。

要求ヘッダーには次の値が必要です。

キー
Content-Type application/json
api-key <your-search-service-api-key>、クエリまたは管理者キーのいずれか

次の例のように、URI パラメーターには、検索サービスのエンドポイントと、インデックス名、docs コレクション、search コマンド、および API バージョンを含める必要があります。

https://{{service-name}}.search.windows.net/indexes/hotels-sample-index/docs/search?api-version=2024-07-01

要求本文は有効な JSON の形式である必要があります。

{
    "search": "*",
    "queryType": "simple",
    "select": "HotelId, HotelName, Category, Tags, Description",
    "count": true
}
  • * に設定された search は null または空の検索に相当する未指定のクエリです。 これは特に便利なわけではありませんが、最も簡単な検索方法であり、インデックス内の取得可能なすべてのフィールドに値がすべて入った状態で表示されます。

  • simple に設定された queryType は既定値であり、省略できますが、この記事のクエリ例が単純な構文で表現されていることを強調するために含まれています。

  • フィールドのコンマ区切りリストに設定した select は、検索結果のコンテキストで有用なフィールドのみが含まれるように検索結果を構成するために使用されます。

  • count は、検索条件に一致するドキュメントの数を返します。 空の検索文字列では、この数はインデックス内のすべてのドキュメントです (hotels-sample-index の場合は 50)。

フルテキスト検索では、ブール演算子の有無にかかわらず、スタンドアロンの用語または引用符で囲んだ語句をいくつでも使用できます。

POST /indexes/hotel-samples-index/docs/search?api-version=2024-07-01
{
    "search": "pool spa +airport",
    "searchMode": "any",
    "queryType": "simple",
    "select": "HotelId, HotelName, Category, Description",
    "count": true
}

重要な用語または語句で構成したキーワード検索が、最もよく機能する傾向があります。 文字列フィールドでは、インデックス作成およびクエリ中にテキスト分析が行われ、theandit などの不必要な単語が削除されます。 クエリ文字列がインデックスでどのようにトークン化されるかを確認するには、Analyze Text 呼び出しで文字列をインデックスに渡します。

searchMode パラメーターは、精度とリコールを制御します。 リコールを増やしたい場合、既定の any 値を使用して、クエリ文字列の一部でも一致した場合に結果を返すようにします。 精度を優先し、文字列の全部が一致することを必須にする場合は、searchModeall に変更します。 両方のやり方で上記のクエリを試して、searchMode によって結果がどのように変わるかを確認してください。

pool spa +airport クエリの応答は次の例のようになります。

"@odata.count": 4,
"value": [
{
    "@search.score": 6.090657,
    "HotelId": "12",
    "HotelName": "Winter Panorama Resort",
    "Description": "Plenty of great skiing, outdoor ice skating, sleigh rides, tubing and snow biking. Yoga, group exercise classes and outdoor hockey are available year-round, plus numerous options for shopping as well as great spa services. Newly-renovated with large rooms, free 24-hr airport shuttle & a new restaurant. Rooms/suites offer mini-fridges & 49-inch HDTVs.",
    "Category": "Resort and Spa"
},
{
    "@search.score": 4.314683,
    "HotelId": "21",
    "HotelName": "Good Business Hotel",
    "Description": "1 Mile from the airport. Free WiFi, Outdoor Pool, Complimentary Airport Shuttle, 6 miles from Lake Lanier & 10 miles from downtown. Our business center includes printers, a copy machine, fax, and a work area.",
    "Category": "Suite"
},
{
    "@search.score": 3.575948,
    "HotelId": "27",
    "HotelName": "Starlight Suites",
    "Description": "Complimentary Airport Shuttle & WiFi. Book Now and save - Spacious All Suite Hotel, Indoor Outdoor Pool, Fitness Center, Florida Green certified, Complimentary Coffee, HDTV",
    "Category": "Suite"
},
{
    "@search.score": 2.6926985,
    "HotelId": "25",
    "HotelName": "Waterfront Scottish Inn",
    "Description": "Newly Redesigned Rooms & airport shuttle. Minutes from the airport, enjoy lakeside amenities, a resort-style pool & stylish new guestrooms with Internet TVs.",
    "Category": "Suite"
}
]

応答の検索スコアに注目してください。 これは一致の関連性スコアです。 既定では、検索サービスはこのスコアに基づいて上位 50 件の一致を返します。

検索がフルテキスト検索でなかったか、条件が指定されていなかったためにランクがない場合は、1.0 の均一のスコアが発生します。 たとえば、空の検索 (search=*) の場合、行は任意の順序で返されます。 実際の基準を含めると、検索スコアは意味のある値に変化します。

例 2: ID による参照

検索結果が返されたら、次の論理的な手順として、ドキュメントからより多くのフィールドを含む詳細ページを指定します。 この例では、Get Document を使用してドキュメント ID を渡して 1 つのドキュメントを返す方法を示します。

GET /indexes/hotels-sample-index/docs/41?api-version=2024-07-01

すべてのドキュメントは一意の識別子を持ちます。 ポータルを使用している場合は、[インデックス] タブからインデックスを選択し、フィールド定義を見てどのフィールドがキーであるかを判断します。 REST API で、GET Index 呼び出しから、応答本文にインデックス定義が返されます。

上記のクエリに対する応答は、キーが 41 であるドキュメントで構成されます。 インデックス定義で retrievable とマークされているすべてのフィールドが検索結果で返され、アプリに表示されます。

{
    "HotelId": "41",
    "HotelName": "Windy Ocean Motel",
    "Description": "Oceanfront hotel overlooking the beach features rooms with a private balcony and 2 indoor and outdoor pools. Inspired by the natural beauty of the island, each room includes an original painting of local scenes by the owner. Rooms include a mini fridge, Keurig coffee maker, and flatscreen TV. Various shops and art entertainment are on the boardwalk, just steps away.",
    "Description_fr": "Cet hôtel en bord de mer donnant sur la plage propose des chambres dotées d'un balcon privé et de 2 piscines intérieure et extérieure. Inspiré par la beauté naturelle de l'île, chaque chambre comprend une peinture originale de scènes locales par le propriétaire. Les chambres comprennent un mini-réfrigérateur, une cafetière Keurig et une télévision à écran plat. Divers magasins et divertissements artistiques se trouvent sur la promenade, à quelques pas.",
    "Category": "Suite",
    "Tags": [
    "pool",
    "air conditioning",
    "bar"
    ],
    "ParkingIncluded": true,
    "LastRenovationDate": "2021-05-10T00:00:00Z",
    "Rating": 3.5,
    "Location": {
    "type": "Point",
    "coordinates": [
        -157.846817,
        21.295841
    ],
    "crs": {
        "type": "name",
        "properties": {
        "name": "EPSG:4326"
        }
    }
    },
    "Address": {
    "StreetAddress": "1450 Ala Moana Blvd 2238 Ala Moana Ctr",
    "City": "Honolulu",
    "StateProvince": "HI",
    "PostalCode": "96814",
    "Country": "USA"
    }
}

例 3: テキストのフィルター

フィルター構文は、単独で使用することも、search と一緒に使用することもできる OData 式です。 同じ要求で一緒に使用した場合、filter が最初にインデックス全体に適用され、次にフィルター処理の結果に対して search が実行されます。 フィルターはクエリのパフォーマンス向上に役立つ手法です。フィルターを使うと、検索クエリで処理が必要なドキュメントの数が減ります。

フィルターは、インデックス定義で filterable とマークされている任意のフィールドに対して定義できます。 hotel-sample-index の場合、フィルター可能なフィールドには、CategoryTagsParkingIncludedRating、ほとんどの Address フィールドが含まれます。

POST /indexes/hotels-sample-index/docs/search?api-version=2024-07-01
{
    "search": "art tours",
    "queryType": "simple",
    "filter": "Category eq 'Boutique'",
    "searchFields": "HotelName,Description,Category",
    "select": "HotelId,HotelName,Description,Category",
    "count": true
}

上記のクエリに対する応答は、Boutique に分類され、用語 art または tours を含むホテルのみがスコープになっています。 この場合、一致するのは 1 件だけです。

"value": [
{
    "@search.score": 1.2814453,
    "HotelId": "2",
    "HotelName": "Old Century Hotel",
    "Description": "The hotel is situated in a nineteenth century plaza, which has been expanded and renovated to the highest architectural standards to create a modern, functional and first-class hotel in which art and unique historical elements coexist with the most modern comforts. The hotel also regularly hosts events like wine tastings, beer dinners, and live music.",
    "Category": "Boutique"
}
]

例 4: フィルター関数

フィルター式に search.ismatch および search.ismatchscoring 関数を含めて、フィルターの中で検索クエリを構築することができます。 このフィルター式では、無料 Wi-Fi、無料駐車場などのアメニティを選択するために、free にワイルドカードを使用しています。

POST /indexes/hotels-sample-index/docs/search?api-version=2024-07-01
  {
    "search": "",
    "filter": "search.ismatch('free*', 'Tags', 'full', 'any')",
    "select": "HotelName, Tags, Description",
    "count": true
  }

上記のクエリに対する応答は、無料のアメニティを提供する 27 のホテルに一致します。 結果全体で検索スコアが均一の "1" であることに注目してください。 これは、検索式が null または空で、結果は逐語的フィルターの一致であり、フルテキスト検索は行われないためです。 関連性スコアは、フルテキスト検索でのみ返されます。 search なしでフィルターを使用している場合は、検索順位を制御できるよう、並べ替え可能なフィールドが十分にあることを確認してください。

  "@odata.count": 27,
  "value": [
    {
      "@search.score": 1,
      "HotelName": "Country Residence Hotel",
      "Description": "All of the suites feature full-sized kitchens stocked with cookware, separate living and sleeping areas and sofa beds. Some of the larger rooms have fireplaces and patios or balconies. Experience real country hospitality in the heart of bustling Nashville. The most vibrant music scene in the world is just outside your front door.",
      "Tags": [
        "laundry service",
        "restaurant",
        "free parking"
      ]
    },
    {
      "@search.score": 1,
      "HotelName": "Downtown Mix Hotel",
      "Description": "Mix and mingle in the heart of the city. Shop and dine, mix and mingle in the heart of downtown, where fab lake views unite with a cheeky design.",
      "Tags": [
        "air conditioning",
        "laundry service",
        "free wifi"
      ]
    },
    {
      "@search.score": 1,
      "HotelName": "Starlight Suites",
      "Description": "Complimentary Airport Shuttle & WiFi. Book Now and save - Spacious All Suite Hotel, Indoor Outdoor Pool, Fitness Center, Florida Green certified, Complimentary Coffee, HDTV",
      "Tags": [
        "pool",
        "coffee in lobby",
        "free wifi"
      ]
    },
. . .

例 5: 範囲フィルター

範囲フィルターは、任意のデータ型のフィルター式を通してサポートされます。 次の例は、数値と文字列の範囲を示しています。 範囲フィルターではデータ型が重要であり、数値フィールドにある数値データと文字列フィールドにある文字列データで最もうまく機能します。 数値文字列は比較できないため、文字列フィールドの数値データは範囲には適していません。

次のクエリは数値範囲です。 hotel-sample-index では、フィルター処理可能な数値フィールドは Rating のみです。

POST /indexes/hotels-sample-index/docs/search?api-version=2024-07-01
{
    "search": "*",
    "filter": "Rating ge 2 and Rating lt 4",
    "select": "HotelId, HotelName, Rating",
    "orderby": "Rating desc",
    "count": true
}

このクエリの応答は、次の例のようになります (簡潔にするため省略しています)。

"@odata.count": 27,
"value": [
{
    "@search.score": 1,
    "HotelId": "22",
    "HotelName": "Lion's Den Inn",
    "Rating": 3.9
},
{
    "@search.score": 1,
    "HotelId": "25",
    "HotelName": "Waterfront Scottish Inn",
    "Rating": 3.8
},
{
    "@search.score": 1,
    "HotelId": "2",
    "HotelName": "Old Century Hotel",
    "Rating": 3.6
},
...

次のクエリは、文字列フィールド (Address/StateProvince) に対する範囲フィルターです。

POST /indexes/hotels-sample-index/docs/search?api-version=2024-07-01
{
    "search": "*",
    "filter": "Address/StateProvince ge 'A*' and Address/StateProvince lt 'D*'",
    "select": "HotelId, HotelName, Address/StateProvince",
    "count": true
}

このクエリの応答は、次の例のようになります (簡潔にするため省略しています)。 この例では、フィールドがインデックス定義で sortable という属性が設定されていないため、StateProvince で並べ替えることはできません。

{
  "@odata.count": 9,
  "value": [
    {
      "@search.score": 1,
      "HotelId": "39",
      "HotelName": "White Mountain Lodge & Suites",
      "Address": {
        "StateProvince": "CO"
      }
    },
    {
      "@search.score": 1,
      "HotelId": "9",
      "HotelName": "Smile Up Hotel",
      "Address": {
        "StateProvince": "CA "
      }
    },
    {
      "@search.score": 1,
      "HotelId": "7",
      "HotelName": "Roach Motel",
      "Address": {
        "StateProvince": "CA "
      }
    },
    {
      "@search.score": 1,
      "HotelId": "34",
      "HotelName": "Lakefront Captain Inn",
      "Address": {
        "StateProvince": "CT"
      }
    },
    {
      "@search.score": 1,
      "HotelId": "37",
      "HotelName": "Campus Commander Hotel",
      "Address": {
        "StateProvince": "CA "
      }
    },
. . . 

hotels-sample インデックスには、緯度と経度の座標を持つ Location フィールドが含まれています。 この例では、geo.distance 関数を使用して、開始点を中心に、指定された距離 (キロメートル単位) に収まるドキュメントをフィルター処理します。 クエリの最後の値 (10) を調整して、クエリのサーフェス領域を拡大または縮小できます。

POST /indexes/v/docs/search?api-version=2024-07-01
{
    "search": "*",
    "filter": "geo.distance(Location, geography'POINT(-122.335114 47.612839)') le 10",
    "select": "HotelId, HotelName, Address/City, Address/StateProvince",
    "count": true
}

このクエリに対する応答は、指定された座標から 10 km 以内の距離にあるすべてのホテルを返します。

{
  "@odata.count": 3,
  "value": [
    {
      "@search.score": 1,
      "HotelId": "45",
      "HotelName": "Happy Lake Resort & Restaurant",
      "Address": {
        "City": "Seattle",
        "StateProvince": "WA"
      }
    },
    {
      "@search.score": 1,
      "HotelId": "24",
      "HotelName": "Uptown Chic Hotel",
      "Address": {
        "City": "Seattle",
        "StateProvince": "WA"
      }
    },
    {
      "@search.score": 1,
      "HotelId": "16",
      "HotelName": "Double Sanctuary Resort",
      "Address": {
        "City": "Seattle",
        "StateProvince": "WA"
      }
    }
  ]
}

例 7: searchMode によるブール値

単純構文では、AND、OR、NOT のクエリ ロジックをサポートするために、文字 (+, -, |) の形式のブール演算子をサポートしています。 ブール型の検索は想定どおりに動作しますが、いくつかの注目すべき例外があります。

ブール検索では、精度と再現率に影響を与えるメカニズムとして、searchMode パラメーターを追加することを検討してください。 有効な値には、再現率を優先する "searchMode": "any" (いずれかの条件を満たすドキュメントが一致と見なされます)、精度を優先する "searchMode": "all" (すべての条件がドキュメント内で一致する必要があります) が含まれます。

ブール検索のコンテキストでは、複数の演算子を使用してクエリをスタックし、結果を狭めるのではなく広げようとしている場合に、既定の "searchMode": "any" は混乱を招く可能性があります。 これは特に NOT に当てはまります。NOT では、特定の用語または語句を "含まない" すべてのドキュメントが結果に含まれます。

具体的な例を次に示します。 クエリは、フレーズ air conditioning を除外する restaurant への一致を検索します。 searchMode (any) を使用して次のクエリを実行すると、43 個のドキュメントが返されます。用語 restaurant を含むものに加えて、フレーズ *air conditioning が存在 "しない" すべてのドキュメントです。

ブール演算子 (-) と語句 air conditioning の間にスペースがないことに注目してください。 引用符はエスケープされます (\")。

POST /indexes/hotels-sample-index/docs/search?api-version=2024-07-01
{
    "search": "restaurant -\"air conditioning\"",
    "searchMode": "any",
    "searchFields": "Tags",
    "select": "HotelId, HotelName, Tags",
    "count": true
}

"searchMode": "all" に変更すると、条件に対する累積効果が適用され、用語 restaurant を含むドキュメントから、語句 air conditioning を含むものを除いて構成される、より小さな結果セット (7 件の一致) が返されます。

このクエリの応答は、次の例のようになりました (簡潔にするため省略しています)。

{
  "@odata.count": 14,
  "value": [
    {
      "@search.score": 3.1383743,
      "HotelId": "18",
      "HotelName": "Ocean Water Resort & Spa",
      "Tags": [
        "view",
        "pool",
        "restaurant"
      ]
    },
    {
      "@search.score": 2.028083,
      "HotelId": "22",
      "HotelName": "Lion's Den Inn",
      "Tags": [
        "laundry service",
        "free wifi",
        "restaurant"
      ]
    },
    {
      "@search.score": 2.028083,
      "HotelId": "34",
      "HotelName": "Lakefront Captain Inn",
      "Tags": [
        "restaurant",
        "laundry service",
        "coffee in lobby"
      ]
    },
...

例 8: 結果のページング

以前の例では、検索結果の構成に影響を与えるパラメーターについて説明しました。たとえば select は、結果に含まれるフィールド、並べ替え順序、すべての一致のカウントを含める方法を決定します。 今回の例は、検索結果の構成の続きです。特定のページに表示する複数の結果をバッチ化するためのページング パラメーターの形式について扱います。

既定では、検索サービスは上位 50 件の一致を返します。 各ページの一致の数を制御するには、top を使用してバッチのサイズを定義した後、skip を使用して後続のバッチを取得します。

並べ替えた結果に対するページングの影響のほうが確認しやすいため、次の例では、Rating フィールドでフィルターと並べ替え順序を使用しています (Rating はフィルター処理と並べ替えの両方が可能です)。 通常の完全検索クエリでは、上位の一致は @search.score によって順位付けおよびページングされます。

POST /indexes/hotels-sample-index/docs/search?api-version=2024-07-01
{
    "search": "*",
    "filter": "Rating gt 4",
    "select": "HotelName, Rating",
    "orderby": "Rating desc",
    "top": 5,
    "count": true
}

このクエリでは 21 件の一致するドキュメントが見つかりますが、top を指定したため、応答では上位 5 件の一致のみが返され、評価は 4.9 が最高、Lakeside B & B の 4.7 が最低になります。

次の 5 件を取得するには、最初のバッチをスキップします。

POST /indexes/hotels-sample-index/docs/search?api-version=2024-07-01
{
    "search": "*",
    "filter": "Rating gt 4",
    "select": "HotelName, Rating",
    "orderby": "Rating desc",
    "top": 5,
    "skip": 5,
    "count": true
}

2 番目のバッチの応答では、最初の 5 件の一致をスキップして、Pull'r Inn Motel から始まる次の 5 件を返します。 それ以降のバッチを取得するには、top は 5 のままにして、(skip=5、skip=10、skip=15 というように) 新しい要求のたびに skip を 5 ずつ大きくします。

{
  "@odata.count": 21,
  "value": [
    {
      "@search.score": 1,
      "HotelName": "Head Wind Resort",
      "Rating": 4.7
    },
    {
      "@search.score": 1,
      "HotelName": "Sublime Palace Hotel",
      "Rating": 4.6
    },
    {
      "@search.score": 1,
      "HotelName": "City Skyline Antiquity Hotel",
      "Rating": 4.5
    },
    {
      "@search.score": 1,
      "HotelName": "Nordick's Valley Motel",
      "Rating": 4.5
    },
    {
      "@search.score": 1,
      "HotelName": "Winter Panorama Resort",
      "Rating": 4.5
    }
  ]
}

基本的なクエリの構文がある程度理解できたら、次は、コードでクエリを指定してみましょう。 次のリンクでは、Azure SDK を使用して検索クエリを設定する方法について説明しています。

追加の構文リファレンス、クエリ アーキテクチャ、およびサンプルについては、次のリンク先を参照してください。