快速入门:使用 REST 进行关键字搜索

Azure AI 搜索中的 REST API 提供了对其所有功能(包括预览功能)的编程访问,并且是了解功能工作原理的一种简单方法。 在本快速入门中,了解如何在 Azure AI 搜索中调用搜索 REST API 来创建、加载和查询搜索索引。

如果没有 Azure 订阅,请在开始前创建一个试用版订阅

先决条件

下载文件

从 GitHub 下载 REST 示例以发送本快速入门中的请求。 有关说明,可参阅从 GitHub 下载文件

你还可以在本地系统上启动一个新文件,并根据本文中的说明手动创建请求。

获取搜索服务终结点

你可以在 Azure 门户中找到搜索服务终结点。

  1. 登录到 Azure 门户查找你的搜索服务

  2. 在“概述”主页上,找到相应 URL。 示例终结点可能类似于 https://mydemo.search.azure.cn

    概述页面上 URL 属性的屏幕截图。

在稍后的步骤中,需将此终结点粘贴到 .rest.http 文件中。

配置访问权限

搜索终结点的请求必须经过身份验证和授权。 你可以使用 API 密钥或角色来完成此任务。 密钥更容易上手,但角色更安全。

对于基于角色的连接,如果按照以下说明操作,你将通过自己的标识(而不是客户端应用的标识)连接到 Azure AI 搜索。

选项 1:使用密钥

选择“设置”>“密钥”,然后复制管理密钥。 管理密钥用于添加、修改和删除对象。 有两个可互换的管理密钥。 复制其中任意一个。 有关详细信息,请参阅使用密钥身份验证连接到 Azure AI 搜索

显示 Azure 门户中的 API 密钥的屏幕截图。

在稍后的步骤中,需将此密钥粘贴到 .rest.http 文件中。

选项 2:使用角色

请确保为基于角色的访问配置搜索服务。 你必须已预先配置用于实现开发人员访问的角色分配。 角色分配必须授予创建、加载和查询搜索索引的权限。

在本部分中,使用 Azure CLI、Azure PowerShell 或 Azure 门户获取个人标识令牌。

  1. 登录到 Azure CLI。

    az cloud set -n AzureChinaCloud
    az login
    # az cloud set -n AzureCloud   //means return to Public Azure.
    
  2. 获取个人标识令牌。

    az account get-access-token --scope https://search.azure.com/.default
    

在稍后的步骤中,需将个人标识令牌粘贴到 .rest.http 文件中。

注意

本部分假定你使用的是代表你连接到 Azure AI 搜索的本地客户端。 另一种方法是获取客户端应用的令牌,前提是你的应用程序已在 Microsoft Entra ID 中注册

设置 Visual Studio Code

如果不熟悉 Visual Studio Code 的 REST 客户端,本部分包括设置,让你能够完成本快速入门中的任务。

  1. 启动 Visual Studio Code 并选择“扩展”磁贴。

  2. 搜索 REST 客户端并选择“安装”。

    屏幕截图显示了 REST 客户端“安装”按钮。

  3. 打开或新建一个文件扩展名为 .rest.http 的文件。

  4. 如果使用 API 密钥,请粘贴以下示例。 请将 @baseUrl@apiKey 占位符替换为之前复制的值。

    @baseUrl = PUT-YOUR-SEARCH-SERVICE-ENDPOINT-HERE
    @apiKey = PUT-YOUR-SEARCH-SERVICE-API-KEY-HERE
    
     ### List existing indexes by name
     GET  {{baseUrl}}/indexes?api-version=2024-07-01&$select=name  HTTP/1.1
       Content-Type: application/json
       api-key: {{apiKey}}
    
  5. 或者,如果使用的是角色,请粘贴此示例。 请将 @baseUrl@token 占位符替换为之前复制的值。

    @baseUrl = PUT-YOUR-SEARCH-SERVICE-ENDPOINT-HERE
    @token = PUT-YOUR-PERSONAL-IDENTITY-TOKEN-HERE
    
     ### List existing indexes by name
     GET  {{baseUrl}}/indexes?api-version=2024-07-01&$select=name  HTTP/1.1
       Content-Type: application/json
       Authorization: Bearer {{token}}
    
  6. 选择“发送请求”。 相邻窗格中应该会显示响应。 如果有现有索引,则会列出它们。 否则,列表将为空。 如果 HTTP 代码为 200 OK,则你已经做好了执行后续步骤的准备。

    屏幕截图显示了为搜索服务请求配置的 REST 客户端。

    要点:

    • 参数是使用 @ 前缀指定的。
    • ### 指定 REST 调用。 下一行包含请求,该请求必须包含 HTTP/1.1
    • Send request 应显示在请求上方。

创建索引

.rest 文件添加第二个请求。 创建索引 (REST) 创建搜索索引并在搜索服务上设置物理数据结构。

  1. 粘贴以下示例,以在搜索服务上创建 hotels-quickstart 索引。

    ### Create a new index
    POST {{baseUrl}}/indexes?api-version=2024-07-01  HTTP/1.1
      Content-Type: application/json
      Authorization: Bearer {{token}}
    
        {
            "name": "hotels-quickstart",  
            "fields": [
                {"name": "HotelId", "type": "Edm.String", "key": true, "filterable": true},
                {"name": "HotelName", "type": "Edm.String", "searchable": true, "filterable": false, "sortable": true, "facetable": false},
                {"name": "Description", "type": "Edm.String", "searchable": true, "filterable": false, "sortable": false, "facetable": false, "analyzer": "en.lucene"},
                {"name": "Category", "type": "Edm.String", "searchable": true, "filterable": true, "sortable": true, "facetable": true},
                {"name": "Tags", "type": "Collection(Edm.String)", "searchable": true, "filterable": true, "sortable": false, "facetable": true},
                {"name": "ParkingIncluded", "type": "Edm.Boolean", "filterable": true, "sortable": true, "facetable": true},
                {"name": "LastRenovationDate", "type": "Edm.DateTimeOffset", "filterable": true, "sortable": true, "facetable": true},
                {"name": "Rating", "type": "Edm.Double", "filterable": true, "sortable": true, "facetable": true},
                {"name": "Address", "type": "Edm.ComplexType", 
                    "fields": [
                    {"name": "StreetAddress", "type": "Edm.String", "filterable": false, "sortable": false, "facetable": false, "searchable": true},
                    {"name": "City", "type": "Edm.String", "searchable": true, "filterable": true, "sortable": true, "facetable": true},
                    {"name": "StateProvince", "type": "Edm.String", "searchable": true, "filterable": true, "sortable": true, "facetable": true},
                    {"name": "PostalCode", "type": "Edm.String", "searchable": true, "filterable": true, "sortable": true, "facetable": true},
                    {"name": "Country", "type": "Edm.String", "searchable": true, "filterable": true, "sortable": true, "facetable": true}
                    ]
                }
            ]
        }
    
  2. 选择“发送请求”。 你应该会有一个 HTTP/1.1 201 Created 响应,并且响应正文应该会包含索引架构的 JSON 表示形式。

    如果收到 Header name must be a valid HTTP token ["{"] 错误,请确保 api-key 与请求正文之间有一个空行。 如果收到 HTTP 504,请验证该 URL 是否指定了 HTTPS。 如果看到 HTTP 400 或 404,请检查请求正文,以验证是否没有复制粘贴错误。 HTTP 403 通常表示 API 密钥存在问题。 要么是密钥无效,要么是指定 API 密钥的方式存在语法问题。

    现在,文件中有多个请求。 回想一下,### 启动了一个新请求,每个请求独立运行。

    屏幕截图显示了包含多个请求的 REST 客户端。

关于索引定义

在索引架构中,字段集合定义了文档结构。 你上传的每个文档都必须具有这些字段。 必须将每个字段分配给一个实体数据模型 (EDM) 数据类型。 字符串字段用于全文搜索。 如果希望数值数据可搜索,请确保数据类型为 Edm.String。 其他数据类型(如 Edm.Int32)可筛选、可排序、可分面、可检索,但不可全文搜索。

字段的属性决定了允许的操作。 默认情况下,REST API 允许很多操作。 例如,默认情况下,所有字符串都是可搜索和可检索的。 对于 REST API,你可能只有在需要关闭某个行为时才需要使用属性。

{
    "name": "hotels-quickstart",  
    "fields": [
        {"name": "HotelId", "type": "Edm.String", "key": true, "filterable": true},
        {"name": "HotelName", "type": "Edm.String", "searchable": true, "filterable": false, "sortable": true, "facetable": false},
        {"name": "Description", "type": "Edm.String", "searchable": true, "filterable": false, "sortable": false, "facetable": false, "analyzer": "en.lucene"},
        {"name": "Category", "type": "Edm.String", "searchable": true, "filterable": true, "sortable": true, "facetable": true},
        {"name": "Tags", "type": "Collection(Edm.String)", "searchable": true, "filterable": true, "sortable": false, "facetable": true},
        {"name": "ParkingIncluded", "type": "Edm.Boolean", "filterable": true, "sortable": true, "facetable": true},
        {"name": "LastRenovationDate", "type": "Edm.DateTimeOffset", "filterable": true, "sortable": true, "facetable": true},
        {"name": "Rating", "type": "Edm.Double", "filterable": true, "sortable": true, "facetable": true},
        {"name": "Address", "type": "Edm.ComplexType", 
        "fields": [
        {"name": "StreetAddress", "type": "Edm.String", "filterable": false, "sortable": false, "facetable": false, "searchable": true},
        {"name": "City", "type": "Edm.String", "searchable": true, "filterable": true, "sortable": true, "facetable": true},
        {"name": "StateProvince", "type": "Edm.String", "searchable": true, "filterable": true, "sortable": true, "facetable": true},
        {"name": "PostalCode", "type": "Edm.String", "searchable": true, "filterable": true, "sortable": true, "facetable": true},
        {"name": "Country", "type": "Edm.String", "searchable": true, "filterable": true, "sortable": true, "facetable": true}
        ]
     }
  ]
}

加载文档

创建和加载索引是两个独立的步骤。 在 Azure AI 搜索中,索引包含所有可搜索的数据,并且查询在搜索服务上运行。 对于 REST 调用,数据以 JSON 文档的形式提供。 为此任务使用文档 - 索引 REST API

需要扩展 URI 以包含 docs 集合和 index 操作。

  1. 粘贴以下示例来将 JSON 文档上传到搜索索引。

    ### Upload documents
    POST {{baseUrl}}/indexes/hotels-quickstart/docs/index?api-version=2024-07-01  HTTP/1.1
      Content-Type: application/json
      Authorization: Bearer {{token}}
    
        {
            "value": [
            {
            "@search.action": "upload",
            "HotelId": "1",
            "HotelName": "Secret Point Motel",
            "Description": "The hotel is ideally located on the main commercial artery of the city in the heart of Beijing. A few minutes away is Time's Square and the historic centre of the city, as well as other places of interest that make Beijing one of America's most attractive and cosmopolitan cities.",
            "Category": "Boutique",
            "Tags": [ "pool", "air conditioning", "concierge" ],
            "ParkingIncluded": false,
            "LastRenovationDate": "1970-01-18T00:00:00Z",
            "Rating": 3.60,
            "Address": 
                {
                "StreetAddress": "677 5th Ave",
                "City": "Beijing",
                "StateProvince": "NY",
                "PostalCode": "10022",
                "Country": "USA"
                } 
            },
            {
            "@search.action": "upload",
            "HotelId": "2",
            "HotelName": "Twin Dome Motel",
            "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.",
            "Category": "Boutique",
            "Tags": [ "pool", "free wifi", "concierge" ],
            "ParkingIncluded": false,
            "LastRenovationDate": "1979-02-18T00:00:00Z",
            "Rating": 3.60,
            "Address": 
                {
                "StreetAddress": "140 University Town Center Dr",
                "City": "Sarasota",
                "StateProvince": "FL",
                "PostalCode": "34243",
                "Country": "USA"
                } 
            },
            {
            "@search.action": "upload",
            "HotelId": "3",
            "HotelName": "Triple Landscape Hotel",
            "Description": "The Hotel stands out for its gastronomic excellence under the management of William Dough, who advises on and oversees all of the Hotel's restaurant services.",
            "Category": "Resort and Spa",
            "Tags": [ "air conditioning", "bar", "continental breakfast" ],
            "ParkingIncluded": true,
            "LastRenovationDate": "2015-09-20T00:00:00Z",
            "Rating": 4.80,
            "Address": 
                {
                "StreetAddress": "3393 Peachtree Rd",
                "City": "Atlanta",
                "StateProvince": "GA",
                "PostalCode": "30326",
                "Country": "USA"
                } 
            },
            {
            "@search.action": "upload",
            "HotelId": "4",
            "HotelName": "Sublime Cliff Hotel",
            "Description": "Sublime Cliff Hotel is located in the heart of the historic center of Sublime in an extremely vibrant and lively area within short walking distance to the sites and landmarks of the city and is surrounded by the extraordinary beauty of churches, buildings, shops and monuments. Sublime Cliff is part of a lovingly restored 1800 palace.",
            "Category": "Boutique",
            "Tags": [ "concierge", "view", "24-hour front desk service" ],
            "ParkingIncluded": true,
            "LastRenovationDate": "1960-02-06T00:00:00Z",
            "Rating": 4.60,
            "Address": 
                {
                "StreetAddress": "7400 San Pedro Ave",
                "City": "San Antonio",
                "StateProvince": "TX",
                "PostalCode": "78216",
                "Country": "USA"
                }
            }
          ]
        }
    
  2. 选择“发送请求”。 几秒后,你应该就会在相邻窗格中看到 HTTP 201 响应。

    如果收到 207,则指示至少有一个文档无法上传。 如果收到 404,则指示请求的标头或正文中有语法错误。 验证你是否已更改终结点来包含 /docs/index

运行查询

现在文档已经加载好,你可以使用文档 - 搜索 POST (REST) 对其发出查询。

需要扩展 URI 以包含查询表达式,查询表达式是使用 /docs/search 运算符指定的。

  1. 粘贴以下示例来查询搜索索引。 然后,选择“发送请求”。 文本搜索请求始终包含 search 参数。 此示例包括一个可选的 searchFields 参数,该参数将文本搜索限制为特定字段。

    ### Run a query
    POST {{baseUrl}}/indexes/hotels-quickstart/docs/search?api-version=2024-07-01  HTTP/1.1
      Content-Type: application/json
      Authorization: Bearer {{token}}
    
      {
          "search": "lake view",
          "select": "HotelId, HotelName, Tags, Description",
          "searchFields": "Description, Tags",
          "count": true
      }
    
  2. 查看相邻窗格中的响应。 你应该会得到一个计数(指示在索引中找到的匹配项数)、一个搜索得分(指示相关性),以及 select 语句中列出的每个字段的值。

    {
      "@odata.context": "https://my-demo.search.azure.cn/indexes('hotels-quickstart')/$metadata#docs(*)",
      "@odata.count": 1,
      "value": [
        {
          "@search.score": 0.6189728,
          "HotelId": "4",
          "HotelName": "Sublime Cliff Hotel",
          "Description": "Sublime Cliff Hotel is located in the heart of the historic center of Sublime in an extremely vibrant and lively area within short walking distance to the sites and landmarks of the city and is surrounded by the extraordinary beauty of churches, buildings, shops and monuments. Sublime Cliff is part of a lovingly restored 1800 palace.",
          "Tags": [
            "concierge",
            "view",
            "24-hour front desk service"
          ]
        }
      ]
    }
    

获取索引属性

还可以使用获取统计信息来查询文档计数和索引大小。

  1. 粘贴以下示例来查询搜索索引。 然后,选择“发送请求”。

    ### Get index statistics
    GET {{baseUrl}}/indexes/hotels-quickstart/stats?api-version=2024-07-01  HTTP/1.1
      Content-Type: application/json
      Authorization: Bearer {{token}}
    
  2. 查看回应。 此操作是获取索引存储详细信息的一种简单方法。

    {
      "@odata.context": "https://my-demo.search.azure.cn/$metadata#Microsoft.Azure.Search.V2023_11_01.IndexStatistics",
      "documentCount": 4,
      "storageSize": 34707,
      "vectorIndexSize": 0
    }
    

清理资源

在自己的订阅中操作时,最好在项目结束时确定是否仍需要已创建的资源。 持续运行资源可能会产生费用。 可以逐个删除资源,也可以删除资源组以删除整个资源集。

可以在门户中使用最左侧窗格中的“所有资源”或“资源组”链接来查找和管理资源。

还可以尝试以下 DELETE 命令:

### Delete an index
DELETE  {{baseUrl}}/indexes/hotels-quickstart?api-version=2024-07-01 HTTP/1.1
    Content-Type: application/json
    api-key: {{apiKey}}

下一步

现在你已经熟悉 REST 客户端并对 Azure AI 搜索进行 REST 调用,接下来请尝试另一篇演示矢量支持的快速入门。