Поделиться через


Краткое руководство: Полнотекстовый поиск

В этом кратком руководстве вы используете клиентскую библиотеку Azure AI Search для .NET для создания, загрузки и запроса индекса поиска для полнотекстового поиска, также известного как поиск по ключевым словам.

Полнотекстовый поиск использует Apache Lucene для индексирования и запросов и алгоритм ранжирования BM25 для результатов оценки. В этом кратком руководстве для заполнения индекса используются вымышленные данные отеля из репозитория azure-search-sample-data GitHub.

Совет

Хотите начать сразу? Скачайте код source на GitHub.

Предварительные условия

  • Учетная запись Azure с активной подпиской. Создайте учетную запись бесплатно .

  • Служба Azure AI Search. Вы можете использовать бесплатную службу для этого краткого руководства.

  • .NET 8 или более поздней версии.

  • Git, чтобы клонировать тестовый репозиторий.

  • Azure CLI для аутентификации без паролей с Microsoft Entra ID.

Настройка доступа

Перед началом работы убедитесь, что у вас есть разрешения на доступ к содержимому и операциям в Azure AI Search. В этой быстрой настройке используется Microsoft Entra ID для аутентификации и доступа с авторизацией на основе ролей. Для назначения ролей необходимо быть владельцем или администратором доступа пользователей . Если роли недоступны, используйте аутентификацию по ключу.

Чтобы настроить рекомендуемый доступ на основе ролей, выполните следующие действия.

  1. Включите доступ на основе ролей для вашего поискового сервиса.

  2. Назначьте следующие роли учетной записи пользователя.

    • Участник сервиса поиска

    • Участник данных индекса поиска

    • Средство чтения индексов поиска

Получение конечной точки

Каждая служба Azure AI Search имеет endpoint, который является уникальным URL-адресом, определяющим и предоставляющим сетевой доступ к службе. В следующем разделе описано, как указать эту конечную точку для программного подключения к службе поиска.

Чтобы получить конечную точку, выполните следующие действия.

  1. Войдите на портал Azure и выберите службу поиска.

  2. В левой области выберите "Обзор".

  3. Запишите конечную точку, которая должна выглядеть следующим образом https://my-service.search.windows.net.

Настройка среды

  1. Используйте Git для клонирования примера репозитория.

    git clone https://github.com/Azure-Samples/azure-search-dotnet-samples
    
  2. Перейдите в папку быстрого запуска.

    cd azure-search-dotnet-samples/quickstart-keyword-search/AzureSearchQuickstart
    
  3. В Program.cs замените значение заполнителя serviceEndpoint на URL-адрес, полученный из метода Get endpoint.

  4. Установите зависимости из AzureSearchQuickstart.csproj.

    dotnet restore
    

    После завершения восстановления убедитесь, что в выходных данных ошибки не отображаются.

  5. Для проверки подлинности без ключа с помощью Microsoft Entra ID войдите в учетную запись Azure. Если у вас несколько подписок, выберите тот, который содержит службу Azure AI Search.

    az login
    

Запустите код

Создайте и запустите приложение.

dotnet run

Выходные данные

Выходные данные должны быть похожи на следующие:

Deleting index...

Creating index...

Uploading documents...

Waiting for indexing...

Starting queries...

Query #1: Search on empty term '*' to return all documents, showing a subset of fields...

HotelId: 3
Name: Gastronomic Landscape Hotel
Rating: 4.8

HotelId: 2
Name: Old Century Hotel
Rating: 3.6

HotelId: 4
Name: Sublime Palace Hotel
Rating: 4.6

HotelId: 1
Name: Stay-Kay City Hotel
Rating: 3.6


Query #2: Search on 'hotels', filter on 'Rating gt 4', sort by Rating in descending order...

HotelId: 3
Name: Gastronomic Landscape Hotel
Rating: 4.8

HotelId: 4
Name: Sublime Palace Hotel
Rating: 4.6


Query #3: Limit search to specific fields (pool in Tags field)...

HotelId: 2
Name: Old Century Hotel
Tags: [ pool, free wifi, concierge ]


Query #4: Facet on 'Category'...

HotelId: 3
Name: Gastronomic Landscape Hotel
Category: Suite

HotelId: 2
Name: Old Century Hotel
Category: Boutique

HotelId: 4
Name: Sublime Palace Hotel
Category: Boutique

HotelId: 1
Name: Stay-Kay City Hotel
Category: Boutique


Query #5: Look up a specific document...

3
Query #6: Call Autocomplete on HotelName...

san
sarasota

Complete. Press any key to end this program...

Общие сведения о коде

Замечание

Фрагменты кода в этом разделе могли быть изменены для удобства чтения. Полный рабочий пример см. в исходном коде.

Теперь, когда вы выполнили код, давайте разберем ключевые шаги:

  1. Создание клиента поиска
  2. Создание индекса поиска
  3. Отправка документов в индекс
  4. Запрос индекса

Создание клиента поиска

В Program.cs вы создаёте два клиента:

  • SearchIndexClient создает индекс.
  • SearchClient загружает и запрашивает существующий индекс.

Оба клиента требуют конечной точки службы и учетных данных для проверки подлинности. В этом кратком руководстве вы используете DefaultAzureCredential для аутентификации без ключа с Microsoft Entra ID.

Создание индекса поиска

В этом кратком руководстве создается индекс отелей, который вы загружаете с данными отеля и выполняете запросы. На этом шаге вы определяете поля в индексе. Каждое определение поля содержит имя, тип данных и атрибуты, которые определяют способ использования этого поля.

В этом примере используются синхронные методы класса SearchIndexClient для простоты и удобства чтения. Однако в рабочих сценариях используйте асинхронные методы, чтобы обеспечить масштабируемость и реагирование приложения. Например, используйте CreateIndexAsync вместо CreateIndex.

Определение структур

Вы создаете два вспомогательных класса Hotel.cs и Address.cs, чтобы определить структуру документа отеля и его адрес. Класс Hotel содержит поля для идентификатора отеля, имени, описания, категории, тегов, парковки, даты обновления, оценки и адреса. Класс Address включает поля для уличных адресов, города, штата или провинции, почтового индекса и страны или региона.

В клиентской библиотеке Azure.Search.Documents можно использовать SearchableField и SimpleField для упрощения определения полей. Оба являются вспомогательными классами, которые создают SearchField и могут потенциально упростить код:

  • SimpleField может быть любым типом данных, всегда недоступен для поиска (игнорируется для запросов полнотекстового поиска) и извлекается (не скрыто). Другие атрибуты отключены по умолчанию, но их можно включить. SimpleField можно использовать для идентификаторов документов или полей, используемых только в фильтрах, фасетах или профилях оценки. Если это так, примените все атрибуты, необходимые для сценария, например IsKey = true для идентификатора документа.

  • SearchableField должен быть строкой и всегда доступен для поиска и извлечения. Другие атрибуты отключены по умолчанию, но их можно включить. Так как этот тип поля доступен для поиска, он поддерживает синонимы и полное дополнение свойств анализатора.

Независимо от того, используется ли базовый API SearchField или одна из вспомогательных моделей, необходимо явно включить атрибуты фильтров, аспектов и сортировки. Например, IsFilterable, IsSortable и IsFacetable должны быть явно атрибутированы, как показано в предыдущем примере.

Создание индекса поиска

В Program.csэтом случае создается объект SearchIndex , а затем вызывается метод CreateOrUpdateIndex для выражения индекса в службе поиска. Индекс также содержит SearchSuggester, чтобы применить автозаполнение для указанных полей.

// Create hotels-quickstart index
private static void CreateIndex(string indexName, SearchIndexClient searchIndexClient)
{
    FieldBuilder fieldBuilder = new FieldBuilder();
    var searchFields = fieldBuilder.Build(typeof(Hotel));

    var definition = new SearchIndex(indexName, searchFields);

    var suggester = new SearchSuggester("sg", new[] { "HotelName", "Category", "Address/City", "Address/StateProvince" });
    definition.Suggesters.Add(suggester);

    searchIndexClient.CreateOrUpdateIndex(definition);
}

Отправка документов в индекс

Azure AI Search выполняет поиск по содержимому, хранящемуся в службе. На этом шаге вы загружаете документы JSON, соответствующие созданному индексу отеля.

В Azure AI Search документы поиска — это структуры данных, которые являются входными данными для индексирования и выходных данных из запросов. В соответствии с данными, полученными из внешних источников, входные данные документа могут быть строками в базе данных, блоками данных в Azure Blob Storage или документами JSON на диске. В этом примере вы используете короткий путь и встраиваете документы JSON для четырех отелей напрямую.

При отправке документов необходимо использовать объект IndexDocumentsBatch. Объект IndexDocumentsBatch содержит коллекцию Actions, каждый из которых содержит документ и свойство, указывающее Azure AI Search какое действие для выполнения (upload, merge, delete и mergeOrUpload).

В Program.cs вы создаете массив документов и действий индексирования, а затем передаете этот массив в IndexDocumentsBatch. Следующие документы соответствуют требованиям индекса hotels-quickstart, как это было определено категорией отеля.

// Upload documents in a single Upload request.
private static void UploadDocuments(SearchClient searchClient)
{
    IndexDocumentsBatch<Hotel> batch = IndexDocumentsBatch.Create(
        IndexDocumentsAction.Upload(
            new Hotel()
            {
                HotelId = "1",
                HotelName = "Stay-Kay City Hotel",
                Description = "This classic hotel is fully-refurbished and ideally located on the main commercial artery of the city in the heart of New York. A few minutes away is Times Square and the historic centre of the city, as well as other places of interest that make New York one of America's most attractive and cosmopolitan cities.",
                Category = "Boutique",
                Tags = new[] { "view", "air conditioning", "concierge" },
                ParkingIncluded = false,
                LastRenovationDate = new DateTimeOffset(2022, 1, 18, 0, 0, 0, TimeSpan.Zero),
                Rating = 3.6,
                Address = new Address()
                {
                    StreetAddress = "677 5th Ave",
                    City = "New York",
                    StateProvince = "NY",
                    PostalCode = "10022",
                    Country = "USA"
                }
            }),
        // REDACTED FOR BREVITY
}

Метод UploadDocuments создает IndexDocumentsBatch и вызывает IndexDocuments в SearchClient для отправки документов. Это краткое руководство получает SearchClient из SearchIndexClient с использованием GetSearchClient, которое повторно использует те же учетные данные.

SearchClient ingesterClient = searchIndexClient.GetSearchClient(indexName);

// Load documents
Console.WriteLine("{0}", "Uploading documents...\n");
UploadDocuments(ingesterClient);

Так как это консольное приложение выполняет все команды последовательно, код добавляет двух секундное время ожидания между индексированием и запросами.

// Wait 2 seconds for indexing to complete before starting queries (for demo and console-app purposes only)
Console.WriteLine("Waiting for indexing...\n");
System.Threading.Thread.Sleep(2000);

Двухсекундная задержка компенсирует индексирование, асинхронное, чтобы все документы можно индексировать перед выполнением запросов. Задержки в коде обычно используются только в демонстрациях, тестах и примерах приложений.

Запрос индекса

Результаты запросов можно получить сразу по завершении индексирования первого документа, но для полноценного тестирования индекса придется подождать, пока закончится индексирование всех документов.

В этом разделе добавлены два элемента функциональности: логика запросов и результаты. Для запросов примените метод Search. Этот метод принимает текст поиска (строку запроса) и другие параметры.

Класс SearchResults представляет результаты запроса.

В Program.csметоде WriteDocuments выводится результаты поиска в консоль.

// Write search results to console
private static void WriteDocuments(SearchResults<Hotel> searchResults)
{
    foreach (SearchResult<Hotel> result in searchResults.GetResults())
    {
        Console.WriteLine(result.Document);
    }

    Console.WriteLine();
}

private static void WriteDocuments(AutocompleteResults autoResults)
{
    foreach (AutocompleteItem result in autoResults.Results)
    {
        Console.WriteLine(result.Text);
    }

    Console.WriteLine();
}

Пример запроса 1

Метод RunQueries выполняет запросы и возвращает результаты. Результаты имеют формат объектов Hotel. В этом примере показана сигнатура метода и первый запрос. Этот запрос демонстрирует Select параметр, позволяющий создавать результат с помощью выбранных полей из документа.

// Run queries, use WriteDocuments to print output
private static void RunQueries(SearchClient searchClient)
{
    SearchOptions options;
    SearchResults<Hotel> response;
    
    // Query 1
    Console.WriteLine("Query #1: Search on empty term '*' to return all documents, showing a subset of fields...\n");

    options = new SearchOptions()
    {
        IncludeTotalCount = true,
        Filter = "",
        OrderBy = { "" }
    };

    options.Select.Add("HotelId");
    options.Select.Add("HotelName");
    options.Select.Add("Rating");

    response = searchClient.Search<Hotel>("*", options);
    WriteDocuments(response);
    // REDACTED FOR BREVITY
}

Пример запроса 2

Во втором запросе выполните поиск по термину, добавьте фильтр, который выбирает документы, где Rating больше 4, а затем сортируйте Rating по убыванию. Фильтр — это логическое выражение, вычисляемое по полям IsFilterable в индексе. Фильтрующие запросы могут включать или исключать указанные значения. Таким образом, оценка релевантности не связана с запросом фильтра.

// Query 2
Console.WriteLine("Query #2: Search on 'hotels', filter on 'Rating gt 4', sort by Rating in descending order...\n");

options = new SearchOptions()
{
    Filter = "Rating gt 4",
    OrderBy = { "Rating desc" }
};

options.Select.Add("HotelId");
options.Select.Add("HotelName");
options.Select.Add("Rating");

response = searchClient.Search<Hotel>("hotels", options);
WriteDocuments(response);

Пример запроса 3

Третий запрос демонстрирует, как используется searchFields, чтобы ограничить полнотекстовый поиск определенными полями.

// Query 3
Console.WriteLine("Query #3: Limit search to specific fields (pool in Tags field)...\n");

options = new SearchOptions()
{
    SearchFields = { "Tags" }
};

options.Select.Add("HotelId");
options.Select.Add("HotelName");
options.Select.Add("Tags");

response = searchClient.Search<Hotel>("pool", options);
WriteDocuments(response);

Пример запроса 4

Четвертый запрос демонстрирует facets, который можно использовать для структуры фасетной навигации.

// Query 4
Console.WriteLine("Query #4: Facet on 'Category'...\n");

options = new SearchOptions()
{
    Filter = ""
};

options.Facets.Add("Category");

options.Select.Add("HotelId");
options.Select.Add("HotelName");
options.Select.Add("Category");

response = searchClient.Search<Hotel>("*", options);
WriteDocuments(response);

Пример запроса 5

В пятом запросе верните конкретный документ. Типичный ответ на событие OnClick в наборе результатов — это поиск документов.

// Query 5
Console.WriteLine("Query #5: Look up a specific document...\n");

Response<Hotel> lookupResponse;
lookupResponse = searchClient.GetDocument<Hotel>("3");

Console.WriteLine(lookupResponse.Value.HotelId);

Пример запроса 6

В последнем запросе показан синтаксис автозавершения, имитирующий частичный пользовательский ввод sa, определяющий два возможных совпадения с авто-подсказчиком, который вы настроили в индексе.

// Query 6
Console.WriteLine("Query #6: Call Autocomplete on HotelName...\n");

var autoresponse = searchClient.Autocomplete("sa", "sg");
WriteDocuments(autoresponse);

Сводка запросов

В предыдущих запросах показано несколько способов сопоставления условий в запросе: полнотекстовый поиск, фильтры и автозавершение.

Метод SearchClient.Search выполняет полнотекстовый поиск и фильтры. Запрос поиска можно передать в строке searchText , пока вы передаете выражение фильтра в свойстве Filter класса SearchOptions . Чтобы выполнить фильтрацию без поиска, передайте "*" в качестве значения параметра searchText в метод Search. Чтобы выполнить поиск без фильтрации, оставьте свойство Filter неустановленным или вообще не передавайте экземпляр SearchOptions.

В этом кратком руководстве по началу работы используется клиентская библиотека Azure AI Search для Java для создания, загрузки и запроса индекса для полнотекстового поиска, также известного как поиск по ключевым словам.

Полнотекстовый поиск использует Apache Lucene для индексирования и запросов и алгоритм ранжирования BM25 для результатов оценки. В этом кратком руководстве для заполнения индекса используются вымышленные данные отеля из репозитория azure-search-sample-data GitHub.

Совет

Хотите начать сразу? Скачайте код source на GitHub.

Предварительные условия

Настройка доступа

Перед началом работы убедитесь, что у вас есть разрешения на доступ к содержимому и операциям в Azure AI Search. В этой быстрой настройке используется Microsoft Entra ID для аутентификации и доступа с авторизацией на основе ролей. Для назначения ролей необходимо быть владельцем или администратором доступа пользователей . Если роли недоступны, используйте аутентификацию по ключу.

Чтобы настроить рекомендуемый доступ на основе ролей, выполните следующие действия.

  1. Включите доступ на основе ролей для вашего поискового сервиса.

  2. Назначьте следующие роли учетной записи пользователя.

    • Участник сервиса поиска

    • Участник данных индекса поиска

    • Средство чтения индексов поиска

Получение конечной точки

Каждая служба Azure AI Search имеет endpoint, который является уникальным URL-адресом, определяющим и предоставляющим сетевой доступ к службе. В следующем разделе описано, как указать эту конечную точку для программного подключения к службе поиска.

Чтобы получить конечную точку, выполните следующие действия.

  1. Войдите на портал Azure и выберите службу поиска.

  2. В левой области выберите "Обзор".

  3. Запишите конечную точку, которая должна выглядеть следующим образом https://my-service.search.windows.net.

Настройка среды

  1. Используйте Git для клонирования примера репозитория.

    git clone https://github.com/Azure-Samples/azure-search-java-samples
    
  2. Перейдите в папку быстрого запуска.

    cd azure-search-java-samples/quickstart-keyword-search
    
  3. В src/main/java/azure/search/sample/App.java замените значение заполнителя searchServiceEndpoint на URL-адрес, полученный из метода Get endpoint.

  4. Установите зависимости.

    mvn clean dependency:copy-dependencies
    

    По завершении сборки убедитесь, что в выходных данных ошибки не отображаются.

  5. Для проверки подлинности без ключа с помощью Microsoft Entra ID войдите в учетную запись Azure. Если у вас несколько подписок, выберите тот, который содержит службу Azure AI Search.

    az login
    

Запустите код

Скомпилируйте и запустите приложение.

javac -d target/classes -cp "target/dependency/*" src/main/java/azure/search/sample/*.java
java -cp "target/classes;target/dependency/*" azure.search.sample.App

Выходные данные

Выходные данные должны быть похожи на следующие:

Waiting for indexing...

Starting queries...

Query #1: Search on empty term '*' to return all documents, showing a subset of fields...

{"HotelId":"3","HotelName":"Gastronomic Landscape Hotel","Address":{"City":"Atlanta"}}
{"HotelId":"2","HotelName":"Old Century Hotel","Address":{"City":"Sarasota"}}
{"HotelId":"4","HotelName":"Sublime Palace Hotel","Address":{"City":"San Antonio"}}
{"HotelId":"1","HotelName":"Stay-Kay City Hotel","Address":{"City":"New York"}}

Query #2: Search on 'hotels', filter on 'Rating gt 4', sort by Rating in descending order...

{"HotelId":"3","HotelName":"Gastronomic Landscape Hotel","Rating":4.8}
{"HotelId":"4","HotelName":"Sublime Palace Hotel","Rating":4.6}

Query #3: Limit search to specific fields (pool in Tags field)...

{"HotelId":"2","HotelName":"Old Century Hotel","Tags":["pool","free wifi","concierge"]}

Query #4: Facet on 'Category'...

{"HotelId":"3","HotelName":"Gastronomic Landscape Hotel","Category":"Suite"}
{"HotelId":"2","HotelName":"Old Century Hotel","Category":"Boutique"}
{"HotelId":"4","HotelName":"Sublime Palace Hotel","Category":"Boutique"}
{"HotelId":"1","HotelName":"Stay-Kay City Hotel","Category":"Boutique"}

Query #5: Look up a specific document...

3

Query #6: Call Autocomplete on HotelName that starts with 's'...

stay
sublime

Complete.

Общие сведения о коде

Замечание

Фрагменты кода в этом разделе могли быть изменены для удобства чтения. Полный рабочий пример см. в исходном коде.

Теперь, когда вы выполнили код, давайте разберем ключевые шаги:

  1. Создание клиента поиска
  2. Создание индекса поиска
  3. Отправка документов в индекс
  4. Запрос индекса

Создание клиента поиска

В App.java вы создаёте два клиента:

  • SearchIndexClient создает индекс.
  • SearchClient загружает и запрашивает существующий индекс.

Оба клиента требуют конечной точки службы и учетных данных для проверки подлинности. В этом кратком руководстве вы используете DefaultAzureCredential для аутентификации без ключа с Microsoft Entra ID.

Создание индекса поиска

В этом кратком руководстве создается индекс отелей, который вы загружаете с данными отеля и выполняете запросы. На этом шаге вы определяете поля в индексе. Каждое определение поля содержит имя, тип данных и атрибуты, которые определяют способ использования этого поля.

В этом примере используются синхронные методы класса SearchIndexClient для простоты и удобства чтения. Однако для рабочих сценариев используйте класс SearchIndexAsyncClient , чтобы обеспечить масштабируемость приложения и реагирование.

Определение структур

Вы создаете два вспомогательных класса Hotel.java и Address.java, чтобы определить структуру документа отеля и его адрес. Класс Hotel содержит поля для идентификатора отеля, имени, описания, категории, тегов, парковки, даты обновления, оценки и адреса. Класс Address включает поля для уличных адресов, города, штата или провинции, почтового индекса и страны или региона.

В клиентской библиотеке azure-search-documents можно использовать SearchableField и SimpleField для упрощения определений полей. Оба являются заметками, которые можно применить к полям или методам для создания SearchField:

  • SimpleField может быть любым типом данных, всегда недоступен для поиска (игнорируется для запросов полнотекстового поиска) и извлекается (не скрыто). Другие атрибуты отключены по умолчанию, но их можно включить. SimpleField можно использовать для идентификаторов документов или полей, используемых только в фильтрах, фасетах или профилях оценки. Если это так, примените все атрибуты, необходимые для сценария, например isKey = true для идентификатора документа.
  • SearchableField должен быть строкой и всегда доступен для поиска и извлечения. Другие атрибуты отключены по умолчанию, но их можно включить. Так как этот тип поля доступен для поиска, он поддерживает синонимы и полное дополнение свойств анализатора.

Независимо от того, используется ли базовый API SearchField или одна из вспомогательных моделей, необходимо явно включить атрибуты фильтров, аспектов и сортировки. Например, isFilterable, isSortable и isFacetable должен быть явно атрибутом, как показано в предыдущем примере.

Создание индекса поиска

В App.java вы создаете объект SearchIndex и затем вызываете метод createOrUpdateIndex для публикации индекса в вашей службе поиска. Индекс также содержит SearchSuggester, чтобы применить автозаполнение для указанных полей.

// Create Search Index for Hotel model
searchIndexClient.createOrUpdateIndex(
    new SearchIndex(indexName, SearchIndexClient.buildSearchFields(Hotel.class, null))
    .setSuggesters(new SearchSuggester("sg", Arrays.asList("HotelName"))));

Отправка документов в индекс

Azure AI Search выполняет поиск по содержимому, хранящемуся в службе. На этом шаге вы загружаете документы JSON, соответствующие созданному индексу отеля.

В Azure AI Search документы поиска — это структуры данных, которые являются входными данными для индексирования и выходных данных из запросов. В соответствии с данными, полученными из внешних источников, входные данные документа могут быть строками в базе данных, блоками данных в Azure Blob Storage или документами JSON на диске. В этом примере вы используете короткий путь и встраиваете документы JSON для четырех отелей напрямую.

При отправке документов необходимо использовать объект IndexDocumentsBatch. Объект IndexDocumentsBatch содержит коллекцию IndexActions, каждая из которых содержит документ и свойство, указывающее Azure AI Search, какое действие следует выполнить (upload, merge, delete или mergeOrUpload).

В App.java вы создаете массив документов и действий индексирования, а затем передаете этот массив в IndexDocumentsBatch. Следующие документы соответствуют требованиям индекса hotels-quickstart, как это было определено категорией отеля.

private static void uploadDocuments(SearchClient searchClient)
{
    var hotelList = new ArrayList<Hotel>();

    var hotel = new Hotel();
    hotel.hotelId = "1";
    hotel.hotelName = "Stay-Kay City Hotel";
    hotel.description = "This classic hotel is fully-refurbished and ideally located on the main commercial artery of the city in the heart of New York. A few minutes away is Times Square and the historic centre of the city, as well as other places of interest that make New York one of America's most attractive and cosmopolitan cities.",
    hotel.category = "Boutique";
    hotel.tags = new String[] { "view", "air conditioning", "concierge" };
    hotel.parkingIncluded = false;
    hotel.lastRenovationDate = OffsetDateTime.of(LocalDateTime.of(LocalDate.of(2022, 1, 18), LocalTime.of(0, 0)), ZoneOffset.UTC);
    hotel.rating = 3.6;
    hotel.address = new Address();
    hotel.address.streetAddress = "677 5th Ave";
    hotel.address.city = "New York";
    hotel.address.stateProvince = "NY";
    hotel.address.postalCode = "10022";
    hotel.address.country = "USA";
    hotelList.add(hotel);
    
    // REDACTED FOR BREVITY

    var batch = new IndexDocumentsBatch<Hotel>();
    batch.addMergeOrUploadActions(hotelList);
    try
    {
        searchClient.indexDocuments(batch);
    }
    catch (Exception e)
    {
        e.printStackTrace();
        // If for some reason any documents are dropped during indexing, you can compensate by delaying and
        // retrying. This simple demo just logs failure and continues
        System.err.println("Failed to index some of the documents");
    }
}

Метод uploadDocuments создает IndexDocumentsBatch и вызывает indexDocuments в SearchClient для отправки документов. В этом быстром старте SearchClient создается независимо с помощью SearchClientBuilder, который требует отдельной настройки конечной точки и учетных данных.

uploadDocuments(searchClient);

Так как это консольное приложение выполняет все команды последовательно, код добавляет двух секундное время ожидания между индексированием и запросами.

// Wait 2 seconds for indexing to complete before starting queries (for demo and console-app purposes only)
System.out.println("Waiting for indexing...\n");
try
{
    Thread.sleep(2000);
}
catch (InterruptedException e)
{
}

Двухсекундная задержка компенсирует индексирование, асинхронное, чтобы все документы можно индексировать перед выполнением запросов. Задержки в коде обычно используются только в демонстрациях, тестах и примерах приложений.

Запрос индекса

Результаты запросов можно получить сразу по завершении индексирования первого документа, но для полноценного тестирования индекса придется подождать, пока закончится индексирование всех документов.

В этом разделе добавлены два элемента функциональности: логика запросов и результаты. Для запросов используйте метод поиска . Этот метод принимает текст поиска (строку запроса) и другие параметры.

Класс SearchPagedIterable представляет результаты.

В App.javaметоде WriteDocuments выводится результаты поиска в консоль.

// Write search results to console
private static void WriteSearchResults(SearchPagedIterable searchResults)
{
    searchResults.iterator().forEachRemaining(result ->
    {
        Hotel hotel = result.getDocument(Hotel.class);
        System.out.println(hotel);
    });

    System.out.println();
}

// Write autocomplete results to console
private static void WriteAutocompleteResults(AutocompletePagedIterable autocompleteResults)
{
    autocompleteResults.iterator().forEachRemaining(result ->
    {
        String text = result.getText();
        System.out.println(text);
    });

    System.out.println();
}

Пример запроса 1

Метод RunQueries выполняет запросы и возвращает результаты. Результаты имеют формат объектов Hotel. В этом примере показана сигнатура метода и первый запрос. Этот запрос демонстрирует Select параметр, позволяющий создавать результат с помощью выбранных полей из документа.

// Run queries, use WriteDocuments to print output
private static void RunQueries(SearchClient searchClient)
{
    // Query 1
    System.out.println("Query #1: Search on empty term '*' to return all documents, showing a subset of fields...\n");

    SearchOptions options = new SearchOptions();
    options.setIncludeTotalCount(true);
    options.setFilter("");
    options.setOrderBy("");
    options.setSelect("HotelId", "HotelName", "Address/City");

    WriteSearchResults(searchClient.search("*", options, Context.NONE));
}

Пример запроса 2

Во втором запросе выполните поиск по термину, добавьте фильтр, который выбирает документы, где Rating больше 4, а затем сортируйте Rating по убыванию. Фильтр — это логическое выражение, вычисляемое по полям isFilterable в индексе. Фильтрующие запросы могут включать или исключать указанные значения. Таким образом, оценка релевантности не связана с запросом фильтра.

// Query 2
System.out.println("Query #2: Search on 'hotels', filter on 'Rating gt 4', sort by Rating in descending order...\n");

options = new SearchOptions();
options.setFilter("Rating gt 4");
options.setOrderBy("Rating desc");
options.setSelect("HotelId", "HotelName", "Rating");

WriteSearchResults(searchClient.search("hotels", options, Context.NONE));

Пример запроса 3

Третий запрос демонстрирует, как используется searchFields, чтобы ограничить полнотекстовый поиск определенными полями.

// Query 3
System.out.println("Query #3: Limit search to specific fields (pool in Tags field)...\n");

options = new SearchOptions();
options.setSearchFields("Tags");

options.setSelect("HotelId", "HotelName", "Tags");

WriteSearchResults(searchClient.search("pool", options, Context.NONE));

Пример запроса 4

Четвертый запрос демонстрирует facets, который можно использовать для структуры фасетной навигации.

// Query 4
System.out.println("Query #4: Facet on 'Category'...\n");

options = new SearchOptions();
options.setFilter("");
options.setFacets("Category");
options.setSelect("HotelId", "HotelName", "Category");

WriteSearchResults(searchClient.search("*", options, Context.NONE));

Пример запроса 5

В пятом запросе верните конкретный документ. Типичный ответ на событие OnClick в наборе результатов — это поиск документов.

// Query 5
System.out.println("Query #5: Look up a specific document...\n");

Hotel lookupResponse = searchClient.getDocument("3", Hotel.class);
System.out.println(lookupResponse.hotelId);
System.out.println();

Пример запроса 6

Последний запрос показывает синтаксис автозавершения, имитируя частичные входные данные пользователя s , разрешающие два возможных совпадения в sourceFields связанном с предложением, определенном в индексе.

// Query 6
System.out.println("Query #6: Call Autocomplete on HotelName that starts with 's'...\n");

WriteAutocompleteResults(searchClient.autocomplete("s", "sg"));

Сводка запросов

В предыдущих запросах показано несколько способов сопоставления условий в запросе: полнотекстовый поиск, фильтры и автозавершение.

Метод SearchClient.search выполняет полнотекстовый поиск и фильтры. Запрос поиска можно передать в строке searchText , пока вы передаете выражение фильтра в свойстве фильтра класса SearchOptions . Чтобы отфильтровать без поиска, просто передайте "*" параметр searchText метода поиска . Чтобы выполнить поиск без фильтрации, оставьте свойство filter неустановленным или вообще не передавайте экземпляр SearchOptions.

В этом кратком руководстве вы используете клиентскую библиотеку Azure AI Search для JavaScript для создания, загрузки и запроса индекса для полнотекстового поиска, также известного как поиск по ключевым словам.

Полнотекстовый поиск использует Apache Lucene для индексирования и запросов и алгоритм ранжирования BM25 для результатов оценки. В этом кратком руководстве для заполнения индекса используются вымышленные данные отеля из репозитория azure-search-sample-data GitHub.

Совет

Хотите начать сразу? Скачайте код source на GitHub.

Предварительные условия

  • Учетная запись Azure с активной подпиской. Создайте учетную запись бесплатно .

  • Служба Azure AI Search. Вы можете использовать бесплатную службу для этого краткого руководства.

  • Node.js 20 LTS или более поздней версии.

  • Git, чтобы клонировать тестовый репозиторий.

  • Azure CLI для аутентификации без паролей с Microsoft Entra ID.

Настройка доступа

Перед началом работы убедитесь, что у вас есть разрешения на доступ к содержимому и операциям в Azure AI Search. В этой быстрой настройке используется Microsoft Entra ID для аутентификации и доступа с авторизацией на основе ролей. Для назначения ролей необходимо быть владельцем или администратором доступа пользователей . Если роли недоступны, используйте аутентификацию по ключу.

Чтобы настроить рекомендуемый доступ на основе ролей, выполните следующие действия.

  1. Включите доступ на основе ролей для вашего поискового сервиса.

  2. Назначьте следующие роли учетной записи пользователя.

    • Участник сервиса поиска

    • Участник данных индекса поиска

    • Средство чтения индексов поиска

Получение конечной точки

Каждая служба Azure AI Search имеет endpoint, который является уникальным URL-адресом, определяющим и предоставляющим сетевой доступ к службе. В следующем разделе описано, как указать эту конечную точку для программного подключения к службе поиска.

Чтобы получить конечную точку, выполните следующие действия.

  1. Войдите на портал Azure и выберите службу поиска.

  2. В левой области выберите "Обзор".

  3. Запишите конечную точку, которая должна выглядеть следующим образом https://my-service.search.windows.net.

Настройка среды

  1. Используйте Git для клонирования примера репозитория.

    git clone https://github.com/Azure-Samples/azure-search-javascript-samples
    
  2. Перейдите в папку быстрого запуска.

    cd azure-search-javascript-samples/quickstart-keyword-search
    
  3. В sample.env замените значение заполнителя SEARCH_API_ENDPOINT на URL-адрес, полученный из метода Get endpoint.

  4. Переименуйте sample.env в .env.

    mv sample.env .env
    
  5. Установите зависимости.

    npm install
    

    После завершения установки в каталоге project должна появиться папка node_modules.

  6. Для проверки подлинности без ключа с помощью Microsoft Entra ID войдите в учетную запись Azure. Если у вас несколько подписок, выберите тот, который содержит службу Azure AI Search.

    az login
    

Запустите код

Запустите приложение.

node index.js

Выходные данные

Выходные данные должны быть похожи на следующие:

Running Azure AI Search Javascript quickstart...
Checking if index exists...
Deleting index...
Creating index...
Index named hotels-quickstart-js has been created.
Uploading documents...
Index operations succeeded: true
Querying the index...

Query #1 - search everything:
{"HotelId":"3","HotelName":"Gastronomic Landscape Hotel","Rating":4.8}
{"HotelId":"2","HotelName":"Old Century Hotel","Rating":3.6}
{"HotelId":"4","HotelName":"Sublime Palace Hotel","Rating":4.6}
{"HotelId":"1","HotelName":"Stay-Kay City Hotel","Rating":3.6}
Result count: 4

Query #2 - search with filter, orderBy, and select:
{"HotelId":"2","HotelName":"Old Century Hotel","Rating":3.6}

Query #3 - limit searchFields:
{"HotelId":"4","HotelName":"Sublime Palace Hotel","Rating":4.6}

Query #4 - limit searchFields and use facets:
{"HotelId":"3","HotelName":"Gastronomic Landscape Hotel","Rating":4.8}
{"HotelId":"2","HotelName":"Old Century Hotel","Rating":3.6}
{"HotelId":"4","HotelName":"Sublime Palace Hotel","Rating":4.6}
{"HotelId":"1","HotelName":"Stay-Kay City Hotel","Rating":3.6}

Query #5 - Lookup document:
HotelId: 3; HotelName: Gastronomic Landscape Hotel

Общие сведения о коде

Замечание

Фрагменты кода в этом разделе могли быть изменены для удобства чтения. Полный рабочий пример см. в исходном коде.

Теперь, когда вы выполнили код, давайте разберем ключевые шаги:

  1. Создание клиента поиска
  2. Создание индекса поиска
  3. Отправка документов в индекс
  4. Запрос индекса

Создание клиента поиска

В index.js вы создаёте два клиента:

  • SearchIndexClient создает индекс.
  • SearchClient загружает и запрашивает существующий индекс.

Оба клиента требуют конечной точки службы и учетных данных для проверки подлинности. В этом кратком руководстве вы используете DefaultAzureCredential для аутентификации без ключа с Microsoft Entra ID.

const credential = new DefaultAzureCredential();
const indexClient = new SearchIndexClient(endpoint, credential);

Создание индекса поиска

В этом кратком руководстве создается индекс отелей, который вы загружаете с данными отеля и выполняете запросы. На этом шаге вы импортируете определение индекса из JSON-файла и создадите индекс в службе поиска.

Файл hotels_quickstart_index.json определяет схему индекса, включая поля и их атрибуты. Каждое поле определяется name и имеет указанный type. Каждое поле также содержит ряд атрибутов индекса, которые указывают, может ли Azure AI Search выполнять поиск, фильтрацию, сортировку и фасетирование по полю. Большинство полей — это простые типы данных, но некоторые из них Addressявляются сложными типами, которые позволяют создавать в индексе расширенные структуры данных. Вы можете подробнее изучить поддерживаемые типы данных и атрибуты индекса, описанные в статье Создание индекса (REST API службы "Когнитивный поиск Azure").

Следующий код импортирует hotels_quickstart_index.json в верхней части index.js, чтобы основная функция могла получить доступ к определению индекса.

const indexDefinition = require('./hotels_quickstart_index.json');

В этом кратком руководстве индекс удаляется, если он уже существует, что является распространенной практикой для тестового и демонстрационного кода. Следующая функция пытается удалить индекс.

async function deleteIndexIfExists(indexClient, indexName) {
    try {
        await indexClient.deleteIndex(indexName);
        console.log('Deleting index...');
    } catch {
        console.log('Index does not exist yet.');
    }
}

Следующий код извлекает имя индекса из определения индекса и передает indexName и indexClient в функцию deleteIndexIfExists().

const indexName = indexDefinition["name"];

console.log('Checking if index exists...');
await deleteIndexIfExists(indexClient, indexName);

После этого вы создадите индекс с помощью метода createIndex().

console.log('Creating index...');
let index = await indexClient.createIndex(indexDefinition);

console.log(`Index named ${index.name} has been created.`);

Отправка документов в индекс

В Azure AI Search документы — это структуры данных, которые являются входными и выходными данными для индексирования и выходных данных из запросов. Эти данные можно отправить в индекс или использовать индексатор. В этом кратком руководстве вы программно отправляете документы в индекс.

Входные данные документа могут быть строками в базе данных, блобами в Azure Blob Storage или JSON-документами на диске, как в этом кратком руководстве. Как и в случае с indexDefinition, вы импортируете hotels.json в верхней части index.js, чтобы получить доступ в главной функции.

const hotelData = require('./hotels.json');

Чтобы индексировать данные в индекс поиска, создайте SearchClient. SearchIndexClient создает и управляет индексом, а SearchClient загружает документы и делает запросы к индексу.

В этом быстром старте SearchClient из SearchIndexClient получается с помощью getSearchClient, который повторно использует те же учетные данные.

const searchClient = indexClient.getSearchClient(indexName);

Следующий код отправляет документы в индекс поиска с помощью mergeOrUploadDocuments() метода, который отправляет документы или объединяет их с существующим документом, если документ с тем же ключом уже существует.

console.log('Uploading documents...');
let indexDocumentsResult = await searchClient.mergeOrUploadDocuments(hotelData['value']);

console.log(`Index operations succeeded: ${JSON.stringify(indexDocumentsResult.results[0].succeeded)}`);

Запрос индекса

С помощью созданного индекса и отправленных документов можно отправлять запросы в индекс. В этом разделе отправляются пять разных запросов в индекс поиска, чтобы продемонстрировать различные функциональность запросов, доступные для вас.

Запросы записываются в функцию, вызываемую в главной sendQueries() функции, следующим образом:

await sendQueries(searchClient);

search() Метод отправки searchClient запросов. Первый параметр — это текст поиска, а второй параметр задает параметры поиска.

Пример запроса 1

Первый запрос выполняет поиск *, что эквивалентно поиску по всем данным, и выбирает три поля в индексе. Рекомендуется использовать select только для нужных вам полей, так как извлечение ненужных данных приведет к задержкам в запросах.

Для searchOptions этого запроса также задано includeTotalCount значение true, которое возвращает количество найденных соответствующих результатов.

async function sendQueries(searchClient) {
    console.log('Query #1 - search everything:');
    let searchOptions = {
        includeTotalCount: true,
        select: ["HotelId", "HotelName", "Rating"]
    };

    let searchResults = await searchClient.search("*", searchOptions);
    for await (const result of searchResults.results) {
        console.log(`${JSON.stringify(result.document)}`);
    }
    console.log(`Result count: ${searchResults.count}`);

    // remaining queries go here
}

Оставшиеся запросы, описанные ниже, также нужно добавить в функцию sendQueries(). Они разделены здесь для удобства чтения.

Пример запроса 2

Следующий запрос указывает поисковый термин "wifi" и включает фильтр, чтобы возвращать только результаты, в которых состояние равно 'FL'. Результаты также упорядочены по критерию отеля Rating. Фильтр — это логическое выражение, вычисляемое по фильтруемым полям в индексе. Фильтрующие запросы могут включать или исключать указанные значения. Таким образом, оценка релевантности не связана с запросом фильтра.

console.log('Query #2 - Search with filter, orderBy, and select:');
let state = 'FL';
searchOptions = {
    filter: odata`Address/StateProvince eq ${state}`,
    orderBy: ["Rating desc"],
    select: ["HotelId", "HotelName", "Rating"]
};

searchResults = await searchClient.search("wifi", searchOptions);
for await (const result of searchResults.results) {
    console.log(`${JSON.stringify(result.document)}`);
}

Пример запроса 3

Третий запрос ограничивает поиск одним полем с возможностью поиска с помощью searchFields параметра. Этот подход является отличным вариантом, чтобы сделать запрос более эффективным, если вы знаете, что вы заинтересованы только в совпадениях в определенных полях.

console.log('Query #3 - Limit searchFields:');
searchOptions = {
    select: ["HotelId", "HotelName", "Rating"],
    searchFields: ["HotelName"]
};

searchResults = await searchClient.search("sublime cliff", searchOptions);
for await (const result of searchResults.results) {
    console.log(`${JSON.stringify(result.document)}`);
}

Пример запроса 4

Еще один распространенный параметр, включаемый в запрос, — facets. С помощью аспектов можно создавать фильтры в пользовательском интерфейсе, чтобы пользователям было проще узнать, какие значения они могут фильтровать. Этот запрос также ограничивает поиск в HotelName поле.

console.log('Query #4 - limit searchFields and use facets:');
searchOptions = {
    facets: ["Category"],
    select: ["HotelId", "HotelName", "Rating"],
    searchFields: ["HotelName"]
};

searchResults = await searchClient.search("*", searchOptions);
for await (const result of searchResults.results) {
    console.log(`${JSON.stringify(result.document)}`);
}

Пример запроса 5

В последнем запросе используется метод getDocument() объекта searchClient. Это позволяет эффективно получать документ по ключу.

console.log('Query #5 - Lookup document:');
let documentResult = await searchClient.getDocument(key='3')
console.log(`HotelId: ${documentResult.HotelId}; HotelName: ${documentResult.HotelName}`)

Сводка запросов

Предыдущие запросы показывают несколько способов сопоставления терминов в запросе: полнотекстовый поиск, фильтры и поиск документов.

Метод searchClient.search выполняет полнотекстовый поиск и фильтры. Запрос поиска можно передать в строке searchText , пока вы передаете выражение фильтра в filter свойстве SearchOptions класса. Чтобы отфильтровать без поиска, просто передайте "*" в качестве параметра searchText метода search. Чтобы выполнить поиск без фильтрации, оставьте свойство filter неустановленным или вообще не передавайте экземпляр SearchOptions.

В этом кратком руководстве вы используете клиентскую библиотеку Azure AI Search для Python для создания, загрузки и запроса индекса поиска для полнотекстового поиска, также известного как поиск по ключевым словам.

Полнотекстовый поиск использует Apache Lucene для индексирования и запросов и алгоритм ранжирования BM25 для результатов оценки. В этом кратком руководстве для заполнения индекса используются вымышленные данные отеля из репозитория azure-search-sample-data GitHub.

Совет

Хотите начать сразу? Скачайте код source на GitHub.

Предварительные условия

Настройка доступа

Перед началом работы убедитесь, что у вас есть разрешения на доступ к содержимому и операциям в Azure AI Search. В этой быстрой настройке используется Microsoft Entra ID для аутентификации и доступа с авторизацией на основе ролей. Для назначения ролей необходимо быть владельцем или администратором доступа пользователей . Если роли недоступны, используйте аутентификацию по ключу.

Чтобы настроить рекомендуемый доступ на основе ролей, выполните следующие действия.

  1. Включите доступ на основе ролей для вашего поискового сервиса.

  2. Назначьте следующие роли учетной записи пользователя.

    • Участник сервиса поиска

    • Участник данных индекса поиска

    • Средство чтения индексов поиска

Получение конечной точки

Каждая служба Azure AI Search имеет endpoint, который является уникальным URL-адресом, определяющим и предоставляющим сетевой доступ к службе. В следующем разделе описано, как указать эту конечную точку для программного подключения к службе поиска.

Чтобы получить конечную точку, выполните следующие действия.

  1. Войдите на портал Azure и выберите службу поиска.

  2. В левой области выберите "Обзор".

  3. Запишите конечную точку, которая должна выглядеть следующим образом https://my-service.search.windows.net.

Настройка среды

  1. Используйте Git для клонирования примера репозитория.

    git clone https://github.com/Azure-Samples/azure-search-python-samples
    
  2. Перейдите в папку быстрого запуска и откройте ее в Visual Studio Code.

    cd azure-search-python-samples/Quickstart-Keyword-Search
    code .
    
  3. Откройте azure-search-quickstart.ipynb.

  4. Нажмите клавиши CTRL+SHIFT+P, выберите записную книжку: выберите ядро записной книжки и следуйте инструкциям по созданию виртуальной среды.

    По завершении вы увидите папку .venv в каталоге проекта.

  5. Запустите первую ячейку кода, чтобы установить необходимые пакеты.

  6. Во второй ячейке кода замените значение заполнителя search_endpoint на URL, полученный на этапе Get endpoint, и выполните ячейку.

  7. Для проверки подлинности без ключа с помощью Microsoft Entra ID войдите в учетную запись Azure. Если у вас несколько подписок, выберите тот, который содержит службу Azure AI Search.

    az login
    

Запустите код

Запустите оставшиеся ячейки кода последовательно, чтобы создать индекс, отправить документы и запросить индекс.

Выходные данные

Каждая ячейка кода выводит выходные данные в записную книжку. Следующий пример — это выходные данные первого запроса, пустой поиск, который возвращает все документы в индексе.

Total Documents Matching Query: 4
1.0
Gastronomic Landscape Hotel
['restaurant', 'bar', 'continental breakfast']
Description: The Gastronomic Hotel stands out for its culinary excellence under the management of William Dough, who advises on and oversees all of the Hotel’s restaurant services.
1.0
Old Century Hotel
['pool', 'free wifi', 'concierge']
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.
1.0
Sublime Palace Hotel
['concierge', 'view', 'air conditioning']
Description: Sublime Palace 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 19th century resort, updated for every modern convenience.
1.0
Stay-Kay City Hotel
['view', 'air conditioning', 'concierge']
Description: This classic hotel is fully-refurbished and ideally located on the main commercial artery of the city in the heart of New York. A few minutes away is Times Square and the historic centre of the city, as well as other places of interest that make New York one of America's most attractive and cosmopolitan cities.

Общие сведения о коде

Замечание

Фрагменты кода в этом разделе могли быть изменены для удобства чтения. Полный рабочий пример см. в исходном коде.

Теперь, когда вы выполнили код, давайте разберем ключевые шаги:

  1. Создание клиентов
  2. Создание индекса поиска
  3. Отправка документов в индекс
  4. Запрос индекса
  5. Удаление индекса

Создание клиентов

Записная книжка создает два клиента:

  • SearchIndexClient создает индексы и управляет ими.
  • SearchClient загружает документы и выполняет запросы.

Для обоих клиентов требуется конечная точка службы и учетные данные. В этом кратком руководстве вы используете DefaultAzureCredential для аутентификации без ключа с Microsoft Entra ID.

Создание индекса поиска

В этом кратком руководстве создается индекс отелей, в который загружаются данные об отелях и выполняются запросы. На этом шаге вы определяете поля в индексе. Каждое определение поля содержит имя, тип данных и атрибуты, которые определяют способ использования этого поля.

Записная книжка использует SimpleField, SearchableField, и ComplexField из пакета моделей для определения схемы. Вы можете подробнее изучить поддерживаемые типы данных и атрибуты индекса, описанные в статье Создание индекса (REST API службы "Когнитивный поиск Azure").

# Create a search schema
index_client = SearchIndexClient(
    endpoint=search_endpoint, credential=credential)
fields = [
        SimpleField(name="HotelId", type=SearchFieldDataType.String, key=True),
        SearchableField(name="HotelName", type=SearchFieldDataType.String, sortable=True),
        SearchableField(name="Description", type=SearchFieldDataType.String, analyzer_name="en.lucene"),
        SearchableField(name="Category", type=SearchFieldDataType.String, facetable=True, filterable=True, sortable=True),

        SearchableField(name="Tags", collection=True, type=SearchFieldDataType.String, facetable=True, filterable=True),

        SimpleField(name="ParkingIncluded", type=SearchFieldDataType.Boolean, facetable=True, filterable=True, sortable=True),
        SimpleField(name="LastRenovationDate", type=SearchFieldDataType.DateTimeOffset, facetable=True, filterable=True, sortable=True),
        SimpleField(name="Rating", type=SearchFieldDataType.Double, facetable=True, filterable=True, sortable=True),

        ComplexField(name="Address", fields=[
            SearchableField(name="StreetAddress", type=SearchFieldDataType.String),
            SearchableField(name="City", type=SearchFieldDataType.String, facetable=True, filterable=True, sortable=True),
            SearchableField(name="StateProvince", type=SearchFieldDataType.String, facetable=True, filterable=True, sortable=True),
            SearchableField(name="PostalCode", type=SearchFieldDataType.String, facetable=True, filterable=True, sortable=True),
            SearchableField(name="Country", type=SearchFieldDataType.String, facetable=True, filterable=True, sortable=True),
        ])
    ]

scoring_profiles = []
suggester = [{'name': 'sg', 'source_fields': ['Tags', 'Address/City', 'Address/Country']}]

# Create the search index=
index = SearchIndex(name=index_name, fields=fields, suggesters=suggester, scoring_profiles=scoring_profiles)
result = index_client.create_or_update_index(index)
print(f' {result.name} created')

Отправка документов в индекс

Azure AI Search выполняет поиск по содержимому, хранящемуся в службе. На этом шаге вы загружаете документы JSON, соответствующие созданному индексу отеля.

В Azure AI Search документы — это структуры данных, которые являются входными и выходными данными для индексирования и выходных данных из запросов. Ноутбук определяет нагрузку документов как список словарей, содержащих информацию об отелях.

# Create a documents payload
documents = [
    {
    "@search.action": "upload",
    "HotelId": "1",
    "HotelName": "Stay-Kay City Hotel",
    "Description": "This classic hotel is fully-refurbished and ideally located on the main commercial artery of the city in the heart of New York. A few minutes away is Times Square and the historic centre of the city, as well as other places of interest that make New York one of America's most attractive and cosmopolitan cities.",
    "Category": "Boutique",
    "Tags": [ "view", "air conditioning", "concierge" ],
    "ParkingIncluded": "false",
    "LastRenovationDate": "2020-01-18T00:00:00Z",
    "Rating": 3.60,
    "Address": {
        "StreetAddress": "677 5th Ave",
        "City": "New York",
        "StateProvince": "NY",
        "PostalCode": "10022",
        "Country": "USA"
        }
    },
    {
    "@search.action": "upload",
    "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",
    "Tags": [ "pool", "free wifi", "concierge" ],
    "ParkingIncluded": "false",
    "LastRenovationDate": "2019-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": "Gastronomic Landscape Hotel",
    "Description": "The Gastronomic Hotel stands out for its culinary excellence under the management of William Dough, who advises on and oversees all of the Hotel’s restaurant services.",
    "Category": "Suite",
    "Tags": [ "restaurant", "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 Palace Hotel",
    "Description": "Sublime Palace 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 19th century resort, updated for every modern convenience.",
    "Category": "Boutique",
    "Tags": [ "concierge", "view", "air conditioning" ],
    "ParkingIncluded": "true",
    "LastRenovationDate": "2020-02-06T00:00:00Z",
    "Rating": 4.60,
    "Address": {
        "StreetAddress": "7400 San Pedro Ave",
        "City": "San Antonio",
        "StateProvince": "TX",
        "PostalCode": "78216",
        "Country": "USA"
        }
    }
]

Метод upload_documents добавляет документы в индекс, создавая их, если они не существуют, или обновляя их, если они существуют.

search_client = SearchClient(endpoint=search_endpoint,
                      index_name=index_name,
                      credential=credential)

try:
    result = search_client.upload_documents(documents=documents)
    print("Upload of new document succeeded: {}".format(result[0].succeeded))
except Exception as ex:
    print (ex.message)

Запрос индекса

Результаты запросов можно получить сразу по завершении индексирования первого документа, но для полноценного тестирования индекса придется подождать, пока закончится индексирование всех документов.

search Используйте метод SearchClient для выполнения запросов.

Примеры запросов в записной книжке демонстрируют распространенные шаблоны:

  • Пустой поиск: выполняет пустой поиск (search_text="*"), возвращая неранжированный список (оценка поиска = 1.0) произвольных документов. Поскольку условия не заданы, в результаты включаются все документы.

  • Поиск терминов: добавляет целые термины в выражение поиска (search_text="wifi"). Этот запрос указывает, что результаты содержат только те поля в параметре select . Ограничение числа полей, которые возвращаются обратно, минимизирует объем данных, передаваемых по сети, и сокращает задержку поиска.

  • Отфильтрованный поиск: добавляет выражение фильтра, возвращая только те отели с рейтингом больше четырех, отсортированные по убыванию.

  • Поле поиска: добавляет search_fields для ограничения выполнения запроса на конкретные поля.

  • Фасетный поиск: создает фасеты для положительных соответствий, найденных в результатах поиска. Нет нулевых совпадений. Если результаты поиска не включают термин "wifi", то "wifi" не отображается в фасетной структуре навигации.

  • Поиск документов: возвращает документ на основе его ключа. Эта операция полезна, если вы хотите предоставить детализацию при выборе элемента в результатах поиска.

  • Автозаполнение: предоставляет возможные совпадения, когда пользователь вводит текст в поле поиска. Автозавершение использует подсказчик (sg), чтобы определить, какие поля содержат потенциальные совпадения с запросами подсказчика. В этом кратком руководстве эти поля: Tags, Address/City, и Address/Country. Чтобы имитировать автозавершение, передайте буквы "sa" как часть строки. Метод autocomplete возвращает потенциальные совпадения с терминами SearchClient.

Удаление индекса

Если вы закончите работу с этим индексом, его можно удалить, выполнив код в ячейке Clean up. Удаление ненужных индексов освобождает пространство для прохождения дополнительных кратких руководств и учебных пособий.

try:
    result = index_client.delete_index(index_name)
    print ('Index', index_name, 'Deleted')
except Exception as ex:
    print (ex)

В этом кратком руководстве вы используете клиентскую библиотеку Azure AI Search для JavaScript (совместимую с TypeScript), чтобы создать, загрузить и запросить индекс поиска для полнотекстового поиска, также известного как поиск по ключевым словам.

Полнотекстовый поиск использует Apache Lucene для индексирования и запросов и алгоритм ранжирования BM25 для результатов оценки. В этом кратком руководстве для заполнения индекса используются вымышленные данные отеля из репозитория azure-search-sample-data GitHub.

Совет

Хотите начать сразу? Скачайте код source на GitHub.

Предварительные условия

  • Учетная запись Azure с активной подпиской. Создайте учетную запись бесплатно .

  • Служба Azure AI Search. Вы можете использовать бесплатную службу для этого краткого руководства.

  • Node.js 20 LTS или более поздней версии для запуска скомпилированного кода.

  • TypeScript для компиляции TypeScript в JavaScript.

  • Git, чтобы клонировать тестовый репозиторий.

  • Azure CLI для аутентификации без паролей с Microsoft Entra ID.

Настройка доступа

Перед началом работы убедитесь, что у вас есть разрешения на доступ к содержимому и операциям в Azure AI Search. В этой быстрой настройке используется Microsoft Entra ID для аутентификации и доступа с авторизацией на основе ролей. Для назначения ролей необходимо быть владельцем или администратором доступа пользователей . Если роли недоступны, используйте аутентификацию по ключу.

Чтобы настроить рекомендуемый доступ на основе ролей, выполните следующие действия.

  1. Включите доступ на основе ролей для вашего поискового сервиса.

  2. Назначьте следующие роли учетной записи пользователя.

    • Участник сервиса поиска

    • Участник данных индекса поиска

    • Средство чтения индексов поиска

Получение конечной точки

Каждая служба Azure AI Search имеет endpoint, который является уникальным URL-адресом, определяющим и предоставляющим сетевой доступ к службе. В следующем разделе описано, как указать эту конечную точку для программного подключения к службе поиска.

Чтобы получить конечную точку, выполните следующие действия.

  1. Войдите на портал Azure и выберите службу поиска.

  2. В левой области выберите "Обзор".

  3. Запишите конечную точку, которая должна выглядеть следующим образом https://my-service.search.windows.net.

Настройка среды

  1. Используйте Git для клонирования примера репозитория.

    git clone https://github.com/Azure-Samples/azure-search-javascript-samples
    
  2. Перейдите в папку быстрого запуска.

    cd azure-search-javascript-samples/quickstart-keyword-search
    
  3. В sample.env замените значение заполнителя SEARCH_API_ENDPOINT на URL-адрес, полученный из метода Get endpoint.

  4. Переименуйте sample.env в .env.

    mv sample.env .env
    
  5. Установите зависимости.

    npm install
    npm install typescript @types/node --save-dev
    npm pkg set type=module
    

    После завершения установки в каталоге project должна появиться папка node_modules.

  6. Для проверки подлинности без ключа с помощью Microsoft Entra ID войдите в учетную запись Azure. Если у вас несколько подписок, выберите тот, который содержит службу Azure AI Search.

    az login
    

Запустите код

В примере кода по умолчанию используется JavaScript. Чтобы запустить код с помощью TypeScript, выполните следующие действия:

  1. Создайте файл с именем tsconfig.jsonи вставьте в него следующий код.

    {
      "compilerOptions": {
        "module": "NodeNext",
        "target": "ES2022",
        "moduleResolution": "NodeNext",
        "skipLibCheck": true,
        "strict": true,
        "resolveJsonModule": true
      },
      "include": ["*.ts"],
      "exclude": ["node_modules"]
    }
    
  2. Переименуйте index.js файл index.tsв , а затем замените содержимое следующим кодом. Этот код преобразует синтаксис CommonJS в импорт модуля ES, необходимый для компиляции TypeScript.

    // Import from the @azure/search-documents library
    import {
        SearchIndexClient,
        SearchClient,
        SearchFieldDataType,
        odata,
        SearchIndex
    } from "@azure/search-documents";
    
    // Import from the Azure Identity library
    import { DefaultAzureCredential } from "@azure/identity";
    
    // Importing the hotels sample data
    import hotelData from './hotels.json' with { type: "json" };
    
    // Load the .env file if it exists
    import "dotenv/config";
    
    // Defining the index definition
    const indexDefinition: SearchIndex = {
    	"name": "hotels-quickstart",
    	"fields": [
    		{
    			"name": "HotelId",
    			"type": "Edm.String" as SearchFieldDataType,
    			"key": true,
    			"filterable": true
    		},
    		{
    			"name": "HotelName",
    			"type": "Edm.String" as SearchFieldDataType,
    			"searchable": true,
    			"filterable": false,
    			"sortable": true,
    			"facetable": false
    		},
    		{
    			"name": "Description",
    			"type": "Edm.String" as SearchFieldDataType,
    			"searchable": true,
    			"filterable": false,
    			"sortable": false,
    			"facetable": false,
    			"analyzerName": "en.lucene"
    		},
    		{
    			"name": "Category",
    			"type": "Edm.String" as SearchFieldDataType,
    			"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" as SearchFieldDataType,
    					"filterable": false,
    					"sortable": false,
    					"facetable": false,
    					"searchable": true
    				},
    				{
    					"name": "City",
    					"type": "Edm.String" as SearchFieldDataType,
    					"searchable": true,
    					"filterable": true,
    					"sortable": true,
    					"facetable": true
    				},
    				{
    					"name": "StateProvince",
    					"type": "Edm.String" as SearchFieldDataType,
    					"searchable": true,
    					"filterable": true,
    					"sortable": true,
    					"facetable": true
    				},
    				{
    					"name": "PostalCode",
    					"type": "Edm.String" as SearchFieldDataType,
    					"searchable": true,
    					"filterable": true,
    					"sortable": true,
    					"facetable": true
    				},
    				{
    					"name": "Country",
    					"type": "Edm.String" as SearchFieldDataType,
    					"searchable": true,
    					"filterable": true,
    					"sortable": true,
    					"facetable": true
    				}
    			]
    		}
    	],
    	"suggesters": [
    		{
    			"name": "sg",
    			"searchMode": "analyzingInfixMatching",
    			"sourceFields": [
    				"HotelName"
    			]
    		}
    	]
    };
    
    async function main() {
    
    	// Your search service endpoint (from .env file)
    	const searchServiceEndpoint = process.env.SEARCH_API_ENDPOINT || "";
    
    	// Use the recommended keyless credential instead of the AzureKeyCredential credential.
    	const credential = new DefaultAzureCredential();
    	//const credential = new AzureKeyCredential(Your search service admin key);
    
    	// Create a SearchIndexClient to send create/delete index commands
    	const searchIndexClient: SearchIndexClient = new SearchIndexClient(
    		searchServiceEndpoint,
    		credential
    	);
    
    	// Creating a search client to upload documents and issue queries
    	const indexName: string  = "hotels-quickstart";
        const searchClient: SearchClient<any> = searchIndexClient.getSearchClient(indexName);
    
        console.log('Checking if index exists...');
        await deleteIndexIfExists(searchIndexClient, indexName);
    
        console.log('Creating index...');
        let index: SearchIndex = await searchIndexClient.createIndex(indexDefinition);
        console.log(`Index named ${index.name} has been created.`);
    
        console.log('Uploading documents...');
        let indexDocumentsResult = await searchClient.mergeOrUploadDocuments(hotelData['value']);
        console.log(`Index operations succeeded: ${JSON.stringify(indexDocumentsResult.results[0].succeeded)} `);
    
        // waiting one second for indexing to complete (for demo purposes only)
        await sleep(1000);
    
        console.log('Querying the index...');
        console.log();
        await sendQueries(searchClient);
    }
    
    async function deleteIndexIfExists(searchIndexClient: SearchIndexClient, indexName: string) {
        try {
            await searchIndexClient.deleteIndex(indexName);
            console.log('Deleting index...');
        } catch {
            console.log('Index does not exist yet.');
        }
    }
    
    async function sendQueries(searchClient: SearchClient<any>) {
        // Query 1
        console.log('Query #1 - search everything:');
        let searchOptions: any = {
            includeTotalCount: true,
            select: ["HotelId", "HotelName", "Rating"]
        };
    
        let searchResults = await searchClient.search("*", searchOptions);
        for await (const result of searchResults.results) {
            console.log(`${JSON.stringify(result.document)}`);
        }
        console.log(`Result count: ${searchResults.count}`);
        console.log();
    
    
        // Query 2
        console.log('Query #2 - search with filter, orderBy, and select:');
        let state = 'FL';
        searchOptions = {
            filter: odata`Address/StateProvince eq ${state}`,
            orderBy: ["Rating desc"],
            select: ["HotelId", "HotelName", "Rating"]
        };
    
        searchResults = await searchClient.search("wifi", searchOptions);
        for await (const result of searchResults.results) {
            console.log(`${JSON.stringify(result.document)}`);
        }
        console.log();
    
        // Query 3
        console.log('Query #3 - limit searchFields:');
        searchOptions = {
            select: ["HotelId", "HotelName", "Rating"],
            searchFields: ["HotelName"]
        };
    
        searchResults = await searchClient.search("sublime palace", searchOptions);
        for await (const result of searchResults.results) {
            console.log(`${JSON.stringify(result.document)}`);
        }
        console.log();
    
        // Query 4
        console.log('Query #4 - limit searchFields and use facets:');
        searchOptions = {
            facets: ["Category"],
            select: ["HotelId", "HotelName", "Rating"],
            searchFields: ["HotelName"]
        };
    
        searchResults = await searchClient.search("*", searchOptions);
        for await (const result of searchResults.results) {
            console.log(`${JSON.stringify(result.document)}`);
        }
        console.log();
    
        // Query 5
        console.log('Query #5 - Lookup document:');
        let documentResult = await searchClient.getDocument('3');
        console.log(`HotelId: ${documentResult.HotelId}; HotelName: ${documentResult.HotelName}`);
        console.log();
    }
    
    function sleep(ms: number) {
        return new Promise(resolve => setTimeout(resolve, ms));
    }
    
    main().catch((err) => {
        console.error("The sample encountered an error:", err);
    });
    
  3. Процесс транспиляции из TypeScript в JavaScript.

    npx tsc
    
  4. Запустите приложение.

    node index.js
    

Выходные данные

Выходные данные должны быть похожи на следующие:

Checking if index exists...
Deleting index...
Creating index...
Index named hotels-quickstart has been created.
Uploading documents...
Index operations succeeded: true 
Querying the index...

Query #1 - search everything:
{"HotelId":"3","HotelName":"Gastronomic Landscape Hotel","Rating":4.8}
{"HotelId":"2","HotelName":"Old Century Hotel","Rating":3.6}
{"HotelId":"4","HotelName":"Sublime Palace Hotel","Rating":4.6}
{"HotelId":"1","HotelName":"Stay-Kay City Hotel","Rating":3.6}
Result count: 4

Query #2 - search with filter, orderBy, and select:
{"HotelId":"2","HotelName":"Old Century Hotel","Rating":3.6}

Query #3 - limit searchFields:
{"HotelId":"4","HotelName":"Sublime Palace Hotel","Rating":4.6}

Query #4 - limit searchFields and use facets:
{"HotelId":"3","HotelName":"Gastronomic Landscape Hotel","Rating":4.8}
{"HotelId":"2","HotelName":"Old Century Hotel","Rating":3.6}
{"HotelId":"4","HotelName":"Sublime Palace Hotel","Rating":4.6}
{"HotelId":"1","HotelName":"Stay-Kay City Hotel","Rating":3.6}

Query #5 - Lookup document:
HotelId: 3; HotelName: Gastronomic Landscape Hotel

Общие сведения о коде

Замечание

Фрагменты кода в этом разделе могли быть изменены для удобства чтения. Полный рабочий пример см. в исходном коде.

Теперь, когда вы выполнили код, давайте разберем ключевые шаги:

  1. Создание клиента поиска
  2. Создание индекса поиска
  3. Отправка документов в индекс
  4. Запрос индекса

Создание клиента поиска

В index.ts вы создаёте два клиента:

  • SearchIndexClient создает индекс.
  • SearchClient загружает и запрашивает существующий индекс.

Оба клиента требуют конечной точки службы и учетных данных для проверки подлинности. В этом кратком руководстве вы используете DefaultAzureCredential для аутентификации без ключа с Microsoft Entra ID.

const credential = new DefaultAzureCredential();
const searchIndexClient: SearchIndexClient = new SearchIndexClient(
    searchServiceEndpoint,
    credential
);

Создание индекса поиска

В этом кратком руководстве создается индекс отелей, который вы загружаете с данными отеля и выполняете запросы. На этом шаге вы определяете поля в индексе.

Объект indexDefinition определяет, как Azure AI Search работает с документами, загруженными на следующем шаге. Каждое поле определяется name и имеет указанный type. Каждое поле также содержит ряд атрибутов индекса, которые указывают, может ли Azure AI Search выполнять поиск, фильтрацию, сортировку и фасетирование по полю. Большинство полей — это простые типы данных, но некоторые из них Addressявляются сложными типами, которые позволяют создавать в индексе расширенные структуры данных. Вы можете подробнее изучить поддерживаемые типы данных и атрибуты индекса, описанные в статье Создание индекса (REST API службы "Когнитивный поиск Azure").

const indexDefinition: SearchIndex = {
    "name": "hotels-quickstart",
    "fields": [
        {
            "name": "HotelId",
            "type": "Edm.String" as SearchFieldDataType,
            "key": true,
            "filterable": true
        },
        {
            "name": "HotelName",
            "type": "Edm.String" as SearchFieldDataType,
            "searchable": true,
            "filterable": false,
            "sortable": true,
            "facetable": false
        },
        // REDACTED FOR BREVITY
    ],
    "suggesters": [
        {
            "name": "sg",
            "searchMode": "analyzingInfixMatching",
            "sourceFields": ["HotelName"]
        }
    ]
};

В этом кратком руководстве индекс удаляется, если он уже существует, что является распространенной практикой для тестового и демонстрационного кода.

async function deleteIndexIfExists(searchIndexClient: SearchIndexClient, indexName: string) {
    try {
        await searchIndexClient.deleteIndex(indexName);
        console.log('Deleting index...');
    } catch {
        console.log('Index does not exist yet.');
    }
}

После этого индекс создается с помощью метода createIndex().

let index: SearchIndex = await searchIndexClient.createIndex(indexDefinition);

Отправка документов в индекс

В Azure AI Search документы — это структуры данных, которые являются входными и выходными данными для индексирования и выходных данных из запросов. Эти данные можно отправить в индекс или использовать индексатор. В этом кратком руководстве вы программно отправляете документы в индекс.

Входные данные документа могут быть строками в базе данных, блобами в Azure Blob Storage или JSON-документами на диске, как в этом кратком руководстве. Данные отеля импортируются в верхней части файла.

import hotelData from './hotels.json' with { type: "json" };

Чтобы индексировать данные в индекс поиска, создайте SearchClient. SearchIndexClient создает и управляет индексом, а SearchClient загружает документы и делает запросы к индексу.

В этом быстром старте SearchClient из SearchIndexClient получается с помощью getSearchClient, который повторно использует те же учетные данные.

const searchClient: SearchClient<any> = searchIndexClient.getSearchClient(indexName);

Метод mergeOrUploadDocuments() отправляет документы или объединяет их с существующим документом, если документ с тем же ключом уже существует.

let indexDocumentsResult = await searchClient.mergeOrUploadDocuments(hotelData['value']);

Запрос индекса

С помощью созданного индекса и отправленных документов можно отправлять запросы в индекс. В этом разделе отправляются пять разных запросов в индекс поиска, чтобы продемонстрировать различные функциональность запросов, доступные для вас.

Запросы записываются в sendQueries() функцию, которая вызывается в главной функции.

await sendQueries(searchClient);

Запросы отправляются с помощью метода search() объекта searchClient. Первый параметр — это текст поиска, а второй параметр задает параметры поиска.

Пример запроса 1

Первый запрос выполняет поиск *, который эквивалентен поиску всего и выбирает три поля в индексе. Рекомендуется использовать select только для нужных вам полей, так как извлечение ненужных данных приведет к задержкам в запросах.

Для searchOptions этого запроса также задано includeTotalCount значение true, которое возвращает количество найденных соответствующих результатов.

console.log('Query #1 - search everything:');
let searchOptions: any = {
    includeTotalCount: true,
    select: ["HotelId", "HotelName", "Rating"]
};

let searchResults = await searchClient.search("*", searchOptions);
for await (const result of searchResults.results) {
    console.log(`${JSON.stringify(result.document)}`);
}
console.log(`Result count: ${searchResults.count}`);

Пример запроса 2

В следующем запросе поисковый термин "wifi" указывается с фильтром, чтобы возвращать только результаты, в которых состояние равно 'FL'. Результаты также упорядочены по критерию отеля Rating.

console.log('Query #2 - search with filter, orderBy, and select:');
let state = 'FL';
searchOptions = {
    filter: odata`Address/StateProvince eq ${state}`,
    orderBy: ["Rating desc"],
    select: ["HotelId", "HotelName", "Rating"]
};

searchResults = await searchClient.search("wifi", searchOptions);
for await (const result of searchResults.results) {
    console.log(`${JSON.stringify(result.document)}`);
}

Пример запроса 3

Поиск ограничен одним полем для поиска с помощью searchFields параметра. Этот подход является отличным вариантом, чтобы сделать запрос более эффективным, если вы знаете, что вы заинтересованы только в совпадениях в определенных полях.

console.log('Query #3 - limit searchFields:');
searchOptions = {
    select: ["HotelId", "HotelName", "Rating"],
    searchFields: ["HotelName"]
};

searchResults = await searchClient.search("sublime palace", searchOptions);
for await (const result of searchResults.results) {
    console.log(`${JSON.stringify(result.document)}`);
}

Пример запроса 4

Еще один распространенный параметр, включаемый в запрос, — facets. Фасеты позволяют выполнять самостоятельное углубление результатов в пользовательском интерфейсе. Результаты фасетов можно превратить в чекбоксы в области результатов.

console.log('Query #4 - limit searchFields and use facets:');
searchOptions = {
    facets: ["Category"],
    select: ["HotelId", "HotelName", "Rating"],
    searchFields: ["HotelName"]
};

searchResults = await searchClient.search("*", searchOptions);
for await (const result of searchResults.results) {
    console.log(`${JSON.stringify(result.document)}`);
}

Пример запроса 5

В последнем запросе используется метод getDocument() объекта searchClient. Это позволяет эффективно получать документ по ключу.

console.log('Query #5 - Lookup document:');
let documentResult = await searchClient.getDocument('3');
console.log(`HotelId: ${documentResult.HotelId}; HotelName: ${documentResult.HotelName}`);

Сводка запросов

Предыдущие запросы показывают несколько способов сопоставления терминов в запросе: полнотекстовый поиск, фильтры и поиск документов.

Метод searchClient.search выполняет полнотекстовый поиск и фильтры. Запрос поиска можно передать в строке searchText , пока вы передаете выражение фильтра в filter свойстве SearchOptions класса. Чтобы отфильтровать без поиска, просто передайте "*" в качестве параметра searchText метода search. Чтобы выполнить поиск без фильтрации, оставьте свойство filter неустановленным или вообще не передавайте экземпляр SearchOptions.

В этом кратком руководстве вы используете REST API Azure AI Search для создания, загрузки и запроса индекса поиска для полнотекстового поиска, также известного как поиск по ключевым словам.

Полнотекстовый поиск использует Apache Lucene для индексирования и запросов и алгоритм ранжирования BM25 для результатов оценки. В этом кратком руководстве для заполнения индекса используются вымышленные данные отеля из репозитория azure-search-sample-data GitHub.

Совет

Хотите начать сразу? Скачайте код source на GitHub.

Предварительные условия

Настройка доступа

Перед началом работы убедитесь, что у вас есть разрешения на доступ к содержимому и операциям в Azure AI Search. В этой быстрой настройке используется Microsoft Entra ID для аутентификации и доступа с авторизацией на основе ролей. Для назначения ролей необходимо быть владельцем или администратором доступа пользователей . Если роли недоступны, используйте аутентификацию по ключу.

Чтобы настроить рекомендуемый доступ на основе ролей, выполните следующие действия.

  1. Включите доступ на основе ролей для вашего поискового сервиса.

  2. Назначьте следующие роли учетной записи пользователя.

    • Участник сервиса поиска

    • Участник данных индекса поиска

    • Средство чтения индексов поиска

Получение конечной точки

Каждая служба Azure AI Search имеет endpoint, который является уникальным URL-адресом, определяющим и предоставляющим сетевой доступ к службе. В следующем разделе описано, как указать эту конечную точку для программного подключения к службе поиска.

Чтобы получить конечную точку, выполните следующие действия.

  1. Войдите на портал Azure и выберите службу поиска.

  2. В левой области выберите "Обзор".

  3. Запишите конечную точку, которая должна выглядеть следующим образом https://my-service.search.windows.net.

Настройка среды

  1. Используйте Git для клонирования примера репозитория.

    git clone https://github.com/Azure-Samples/azure-search-rest-samples
    
  2. Перейдите в папку быстрого запуска и откройте ее в Visual Studio Code.

    cd azure-search-rest-samples/Quickstart-keyword-search
    code .
    
  3. В az-search-quickstart.rest замените значение заполнителя @baseUrl на URL-адрес, полученный из метода Get endpoint.

  4. Для проверки подлинности без ключа с помощью Microsoft Entra ID войдите в учетную запись Azure. Если у вас несколько подписок, выберите тот, который содержит службу Azure AI Search.

    az login
    
  5. Для проверки подлинности без ключа с помощью Microsoft Entra ID создайте маркер доступа.

    az account get-access-token --scope https://search.azure.com/.default --query accessToken -o tsv
    
  6. Замените значение заполнителя @token токеном из предыдущего шага.

Запустите код

  1. В разделе ### List existing indexes by nameвыберите "Отправить запрос" , чтобы проверить подключение.

    Ответ должен отображаться в соседней области. Если у вас уже есть индексы, они будут перечислены. В противном случае список пуст. Если http-код имеет значение 200 OK, вы готовы продолжить работу.

  2. Отправьте остальные запросы последовательно, чтобы создать индекс, отправить документы и запросить индекс.

Выходные данные

Каждый запрос возвращает разные json в зависимости от операции. Ключевой результат должен поступать от ### Run a query и выглядеть следующим образом:

{
  "value": [
    {
      "@search.score": 0.5575875,
      "HotelId": "3",
      "HotelName": "Gastronomic Landscape Hotel",
      "Description": "The Gastronomic Hotel stands out for its culinary excellence under the management of William Dough, who advises on and oversees all of the Hotel's restaurant services.",
      "Tags": [
        "restaurant",
        "bar",
        "continental breakfast"
      ]
    }
  ]
}

Общие сведения о коде

Замечание

Фрагменты кода в этом разделе могли быть изменены для удобства чтения. Полный рабочий пример см. в исходном коде.

Теперь, когда вы выполнили код, давайте разберем ключевые шаги:

  1. Создание индекса поиска
  2. Отправка документов в индекс
  3. Запрос индекса

Создание индекса поиска

Перед добавлением содержимого в Azure AI Search необходимо создать индекс, чтобы определить, как хранится и структурировано содержимое. Индекс концептуально похож на таблицу в реляционной базе данных, но он специально предназначен для операций поиска, таких как полнотекстовый поиск.

В этом кратком руководстве вызывается Индексы - Создание (REST API) для создания индекса поиска с именем hotels-quickstart и его физических структур данных в службе поиска.

В схеме индекса fields коллекция определяет структуру документов отеля. Каждое nameполе имеет данные typeи атрибуты, определяющие его поведение во время индексирования и запросов. Поле HotelId помечается как ключ, который Azure AI Search необходимо для уникальной идентификации каждого документа внутри индекса.

### Create a new index
POST {{baseUrl}}/indexes?api-version={{api-version}}  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}
            ]
        }
    ]
}

Ключевые моменты схемы индекса:

  • Используйте строковые поля (Edm.String) для создания полнотекстового поиска числовых данных. Другие поддерживаемые типы данных, такие как Edm.Int32фильтруемые, сортируемые, фасетные и извлекаемые, но не доступны для поиска.

  • Большинство полей являются простыми типами данных, но можно определить сложные типы для представления вложенных данных, таких как Address поле.

  • Атрибуты полей определяют разрешенные действия. интерфейсы REST API позволяют множество действий по умолчанию. Например, все строки доступны для поиска и извлечения. С интерфейсами REST API можно использовать только атрибуты, если необходимо отключить поведение.

Отправка документов в индекс

Только что созданные индексы пусты. Чтобы заполнить индекс и сделать его доступным для поиска, необходимо отправить документы JSON, соответствующие схеме индекса.

В Azure AI Search документы служат как входными данными для индексирования, так и выходных данных для запросов. Для простоты в этом кратком руководстве приведены образцы документов отеля в виде встроенного JSON-кода. Однако в рабочих сценариях содержимое часто извлекается из подключенных источников данных и преобразуется в JSON с помощью индексаторов.

В этом кратком руководстве приводится вызов Documents - Index (REST API), чтобы добавить в индекс четыре образца документов отеля. По сравнению с предыдущим запросом универсальный код ресурса (URI) расширен для включения docs коллекции и index операции.

Каждый документ в массиве value представляет отель и содержит поля, соответствующие схеме индекса. Параметр @search.action задает операцию, выполняемую для каждого документа. В этом примере используется upload, который добавляет документ, если он не существует или обновляет документ, если он существует.

### Upload documents
POST {{baseUrl}}/indexes/hotels-quickstart/docs/index?api-version={{api-version}}  HTTP/1.1
Content-Type: application/json
Authorization: Bearer {{token}}

{
    "value": [
        {
            "@search.action": "upload",
            "HotelId": "1",
            "HotelName": "Stay-Kay City Hotel",
            "Description": "This classic hotel is fully-refurbished and ideally located on the main commercial artery of the city in the heart of New York. A few minutes away is Times Square and the historic centre of the city, as well as other places of interest that make New York one of America's most attractive and cosmopolitan cities.",
            "Category": "Boutique",
            "Tags": [ "view", "air conditioning", "concierge" ],
            "ParkingIncluded": false,
            "LastRenovationDate": "2022-01-18T00:00:00Z",
            "Rating": 3.60,
            "Address": 
            {
                "StreetAddress": "677 5th Ave",
                "City": "New York",
                "StateProvince": "NY",
                "PostalCode": "10022",
                "Country": "USA"
            } 
        },
        {
            "@search.action": "upload",
            "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",
            "Tags": [ "pool", "free wifi", "concierge" ],
            "ParkingIncluded": false,
            "LastRenovationDate": "2019-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": "Gastronomic Landscape Hotel",
            "Description": "The Gastronomic Hotel stands out for its culinary excellence under the management of William Dough, who advises on and oversees all of the Hotel’s restaurant services.",
            "Category": "Suite",
            "Tags": [ "restaurant", "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 Palace Hotel",
            "Description": "Sublime Palace 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 19th century resort, updated for every modern convenience.",
            "Tags": [ "concierge", "view", "air conditioning" ],
            "ParkingIncluded": true,
            "LastRenovationDate": "2020-02-06T00:00:00Z",
            "Rating": 4.60,
            "Address": 
            {
                "StreetAddress": "7400 San Pedro Ave",
                "City": "San Antonio",
                "StateProvince": "TX",
                "PostalCode": "78216",
                "Country": "USA"
            }
        }
    ]
}

Запрос индекса

Теперь, когда документы загружаются в индекс, можно использовать полнотекстовый поиск для поиска определенных терминов или фраз в своих полях.

В этом кратком руководстве вызывается Documents - Search Post (REST API), чтобы найти документы отеля, которые соответствуют вашим критериям поиска. Теперь URI предназначен для выполнения операции /docs/search.

Запросы полнотекстового search поиска всегда включают параметр, содержащий текст запроса. Текст запроса может содержать один или несколько терминов, фраз или операторов. Кроме того search, можно указать другие параметры для уточнения поведения и результатов поиска.

Запрос ищет термины "присоединенный ресторан" в Description полях Tags каждого документа отеля. Параметр select ограничивает поля, возвращаемые в ответе, такими как HotelId, HotelName, Tags и Description. Параметр count запрашивает общее количество соответствующих документов.

### Run a query
POST {{baseUrl}}/indexes/hotels-quickstart/docs/search?api-version={{api-version}}  HTTP/1.1
Content-Type: application/json
Authorization: Bearer {{token}}

{
    "search": "attached restaurant",
    "select": "HotelId, HotelName, Tags, Description",
    "searchFields": "Description, Tags",
    "count": true
}

В этом кратком руководстве вы используете PowerShell и REST API Azure AI Search для создания, загрузки и запроса индекса для полнотекстового поиска, также известного как поиск по ключевым словам.

Полнотекстовый поиск использует Apache Lucene для индексирования и запросов и алгоритм ранжирования BM25 для результатов оценки. В этом кратком руководстве для заполнения индекса используются вымышленные данные отеля из репозитория azure-search-sample-data GitHub.

Совет

Хотите начать сразу? Скачайте код source на GitHub.

Предварительные условия

  • Учетная запись Azure с активной подпиской. Создайте учетную запись бесплатно .

  • Служба Azure AI Search. Вы можете использовать бесплатную службу для этого краткого руководства.

  • PowerShell 7 или более поздней версии.

  • Git, чтобы клонировать тестовый репозиторий.

  • Azure CLI для аутентификации без паролей с Microsoft Entra ID.

Настройка доступа

Перед началом работы убедитесь, что у вас есть разрешения на доступ к содержимому и операциям в Azure AI Search. В этой быстрой настройке используется Microsoft Entra ID для аутентификации и доступа с авторизацией на основе ролей. Для назначения ролей необходимо быть владельцем или администратором доступа пользователей . Если роли недоступны, используйте аутентификацию по ключу.

Чтобы настроить рекомендуемый доступ на основе ролей, выполните следующие действия.

  1. Включите доступ на основе ролей для вашего поискового сервиса.

  2. Назначьте следующие роли учетной записи пользователя.

    • Участник сервиса поиска

    • Участник данных индекса поиска

    • Средство чтения индексов поиска

Получение конечной точки

Каждая служба Azure AI Search имеет endpoint, который является уникальным URL-адресом, определяющим и предоставляющим сетевой доступ к службе. В следующем разделе описано, как указать эту конечную точку для программного подключения к службе поиска.

Чтобы получить конечную точку, выполните следующие действия.

  1. Войдите на портал Azure и выберите службу поиска.

  2. В левой области выберите "Обзор".

  3. Запишите конечную точку, которая должна выглядеть следующим образом https://my-service.search.windows.net.

Настройка среды

  1. Используйте Git для клонирования примера репозитория.

    git clone https://github.com/Azure-Samples/azure-search-powershell-samples
    
  2. Перейдите в папку быстрого запуска.

    cd azure-search-powershell-samples/Quickstart
    
  3. Для проверки подлинности без ключа с помощью Microsoft Entra ID войдите в учетную запись Azure. Если у вас несколько подписок, выберите тот, который содержит службу Azure AI Search.

    az login
    
  4. В azure-search-quickstart.ps1 замените значение заполнителя $baseUrl на URL-адрес, полученный из метода Get endpoint.

Запустите код

В том же терминале выполните следующий скрипт PowerShell, чтобы выполнить этот быстрый старт.

.\azure-search-quickstart.ps1

Выходные данные

Скрипт удаляет любой существующий индекс, создает новый индекс, отправляет документы и выполняет несколько полнотекстовых запросов поиска. В выходных данных показаны полные HTTP-запросы и ответы для каждой операции. В следующем примере показан ответ при поиске "ресторан wifi".

{
  "value": [
    {
      "@search.score": 0.6931472,
      "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.",
      "Tags": ["pool", "free wifi", "concierge"]
    },
    {
      "@search.score": 0.5575875,
      "HotelName": "Gastronomic Landscape Hotel",
      "Description": "The Gastronomic Hotel stands out for its culinary excellence under the management of William Dough, who advises on and oversees all of the Hotel's restaurant services.",
      "Tags": ["restaurant", "bar", "continental breakfast"]
    }
  ]
}

Общие сведения о коде

Замечание

Фрагменты кода в этом разделе могли быть изменены для удобства чтения. Полный рабочий пример см. в исходном коде.

Теперь, когда вы выполнили код, давайте разберем ключевые шаги:

  1. Создание индекса поиска
  2. Отправка документов в индекс
  3. Запрос индекса

Создание индекса поиска

Перед добавлением содержимого в Azure AI Search необходимо создать индекс, чтобы определить, как хранится и структурировано содержимое. Индекс концептуально похож на таблицу в реляционной базе данных, но он специально предназначен для операций поиска, таких как полнотекстовый поиск.

В этом кратком руководстве сначала удаляется любой существующий индекс с тем же именем, что является распространенной практикой для тестового и демонстрационного кода, который выполняется многократно.

Send-Request DELETE "$baseUrl/indexes/hotels-quickstart?api-version=2025-09-01" $headers

В этом кратком руководстве затем вызывается Индексы — создание (REST API) для построения индекса поиска с именем hotels-quickstart и его физической структуры данных в службе поиска.

$body = @"
{
    "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"},
        ...
    ]
}
"@

Send-RequestWithBody POST "$baseUrl/indexes?api-version=2025-09-01" $headers $body

В схеме индекса fields коллекция определяет структуру документов отеля. Каждое nameполе имеет данные typeи атрибуты, определяющие его поведение во время индексирования и запросов. Поле HotelId помечается как ключ, который Azure AI Search необходимо для уникальной идентификации каждого документа внутри индекса.

Ключевые моменты схемы индекса:

  • Используйте строковые поля (Edm.String) для создания полнотекстового поиска числовых данных. Другие поддерживаемые типы данных, такие как Edm.Int32фильтруемые, сортируемые, фасетные и извлекаемые, но не доступны для поиска.

  • Большинство полей являются простыми типами данных, но можно определить сложные типы для представления вложенных данных, таких как Address поле.

  • Атрибуты полей определяют разрешенные действия. интерфейсы REST API позволяют множество действий по умолчанию. Например, все строки доступны для поиска и извлечения. С интерфейсами REST API можно использовать только атрибуты, если необходимо отключить поведение.

Отправка документов в индекс

Только что созданные индексы пусты. Чтобы заполнить индекс и сделать его доступным для поиска, необходимо отправить документы JSON, соответствующие схеме индекса.

В Azure AI Search документы служат как входными данными для индексирования, так и выходных данных для запросов. Для простоты в этом кратком руководстве приведены образцы документов отеля в виде встроенного JSON-кода. Однако в рабочих сценариях содержимое часто извлекается из подключенных источников данных и преобразуется в JSON с помощью индексаторов.

В этом кратком руководстве приводится вызов Documents - Index (REST API), чтобы добавить в индекс четыре образца документов отеля. По сравнению с предыдущим запросом универсальный код ресурса (URI) расширен для включения docs коллекции и index операции.

$body = @"
{
    "value": [
        {
            "@search.action": "upload",
            "HotelId": "1",
            "HotelName": "Stay-Kay City Hotel",
            "Description": "This classic hotel is...",
            ...
        },
        ...
    ]
}
"@

Send-RequestWithBody POST "$baseUrl/indexes/hotels-quickstart/docs/index?api-version=2025-09-01" $headers $body

Каждый документ в массиве value представляет отель и содержит поля, соответствующие схеме индекса. Параметр @search.action задает операцию, выполняемую для каждого документа. В этом примере используется upload, который добавляет документ, если он не существует или обновляет документ, если он существует.

Запрос индекса

Теперь, когда документы загружаются в индекс, можно использовать полнотекстовый поиск для поиска определенных терминов или фраз в своих полях.

В этом кратком руководстве вызывается Documents - Search Post (REST API), чтобы найти документы отеля, которые соответствуют вашим критериям поиска. Унифицированный идентификатор ресурса (URI) нацелен на /docs/search операцию.

Запросы полнотекстового поиска включают параметр с текстом search запроса, который может содержать термины, фразы или операторы. Запрос выполняет поиск по всем полям, которые можно найти в каждом документе. В следующих примерах показаны распространенные шаблоны запросов.

Пример запроса 1

Следующий запрос выполняет поиск терминов "ресторан wifi" во всех полях, доступных для поиска. По умолчанию Azure AI Search возвращает документы, соответствующие любому из условий поиска.

$body = @"
{
    "search": "restaurant wifi",
    "select": "HotelName, Description, Tags"
}
"@

Send-RequestWithBody POST "$baseUrl/indexes/hotels-quickstart/docs/search?api-version=2025-09-01" $headers $body

Параметр select ограничивает поля, возвращаемые в ответе HotelName, Descriptionи Tags.

Пример запроса 2

Следующий запрос использует выражение для возврата только отелей с рейтингом filter больше 4.

$body = @"
{
    "search": "*",
    "filter": "Rating gt 4",
    "select": "HotelName,Rating"
}
"@

Send-RequestWithBody POST "$baseUrl/indexes/hotels-quickstart/docs/search?api-version=2025-09-01" $headers $body

Для search параметра задано *значение , которое соответствует всем документам. Параметр filter применяет логическое условие, чтобы сузить результаты.

Пример запроса 3

Следующий запрос ищет "бутик" и использует top для возврата только первых двух результатов.

$body = @"
{
    "search": "boutique",
    "select": "HotelName,Category",
    "top": 2
}
"@

Send-RequestWithBody POST "$baseUrl/indexes/hotels-quickstart/docs/search?api-version=2025-09-01" $headers $body

Пример запроса 4

Следующий запрос ищет "пул" и использует orderby для сортировки результатов Rating по убыванию.

$body = @"
{
    "search": "pool",
    "select": "HotelName,Description,Tags,Rating",
    "orderby": "Rating desc"
}
"@

Send-RequestWithBody POST "$baseUrl/indexes/hotels-quickstart/docs/search?api-version=2025-09-01" $headers $body

Очистите ресурсы

При работе с собственной подпиской рекомендуется завершить проект, удалив ресурсы, которые больше не нужны. Ресурсы, оставленные работающими, могут стоить вам денег.

На портале Azure выберите All resources или Resource groups на панели слева, чтобы найти ресурсы и управлять ими. Вы можете удалить ресурсы по отдельности или удалить группу ресурсов, чтобы удалить все ресурсы одновременно.

Если вы используете бесплатную службу поиска, помните, что вы ограничены тремя индексами, индексаторами и источниками данных. Вы можете удалить отдельные элементы на портале, чтобы остаться в пределах ограничения.