Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
В этой статье приведено краткое руководство по C# для устаревшей клиентской библиотеки Microsoft.Azure.Search (версия 10), замененной клиентской библиотекой Azure.Search.Documents (версия 11).
Замечание
Если у вас есть уже начатые или текущие проекты разработки, вы можете продолжать использовать версию 10. Но для новых проектов или использования новых функций следует перейти в новую библиотеку.
Об этом кратком руководстве
Создайте консольное приложение .NET Core на C#, которое создает, загружает и запрашивает индекс Когнитивного поиска Azure с помощью Visual Studio и клиентских библиотек Microsoft.Azure.Search.
В этой статье объясняется, как создать приложение. Вы также можете скачать и запустить полное приложение.
Замечание
Демонстрационный код в этой статье использует синхронные методы пакета SDK для Когнитивного поиска Azure версии 10 .NET для простоты. Однако в рабочих сценариях рекомендуется использовать асинхронные методы в собственных приложениях, чтобы обеспечить их масштабируемость и реагирование. Например, можно использовать CreateAsync и DeleteAsync вместо Create и Delete.
Предпосылки
Перед началом работы убедитесь, что у вас есть следующее.
Учетная запись Azure с активной подпиской. Создайте учетную запись бесплатно .
Служба Когнитивного поиска Azure. Создайте службу или найдите имеющуюся службу в рамках текущей подписки. Вы можете использовать бесплатный сервис для этого быстрого старта.
Visual Studio (любой версии). Пример кода и инструкции были протестированы в бесплатной версии Community edition.
Получение ключа и URL-адреса
Для вызовов службы требуется конечная точка URL-адреса и ключ доступа для каждого запроса. Служба поиска создается вместе с этими службами, поэтому если вы добавили Когнитивный поиск Azure в подписку, выполните следующие действия, чтобы получить необходимые сведения:
Войдите на портал Azure и на странице обзора службы поиска получите URL-адрес. Пример конечной точки может выглядеть так:
https://mydemo.search.windows.net.In Settings>Keys, get an admin key for full rights on the service. Существуют два взаимозаменяемых ключа администратора, предназначенных для обеспечения непрерывности бизнес-процессов на случай, если вам потребуется сменить один из них. Вы можете использовать первичный или вторичный ключ для выполнения запросов на добавление, изменение и удаление объектов.
Получите также ключ запроса. Рекомендуется в качестве наилучшей практики осуществлять запросы с доступом только для чтения.
Для всех запросов требуется ключ API для каждого запроса, отправленного в службу. Наличие валидного ключа устанавливает доверие на основе каждого запроса между приложением, отправляющим запрос, и службой, обрабатывающей его.
Настройка среды
Сначала откройте Visual Studio и создайте новый проект консольного приложения, которое будет выполняться на базе .NET Core.
Установка пакетов Nuget
Пакет Microsoft.Azure.Search состоит из нескольких клиентских библиотек, распределенных как пакеты NuGet.
Для этого проекта используйте версию 10 Microsoft.Azure.Search пакета NuGet и последний Microsoft.Extensions.Configuration.Json пакет NuGet.
В разделе Инструменты>Диспетчер пакетов NuGet выберите Управление пакетами NugGet для решения....
Нажмите кнопку Обзор.
Microsoft.Azure.SearchНайдите и выберите версию 10.Нажмите кнопку "Установить " справа, чтобы добавить сборку в проект и решение.
Microsoft.Extensions.Configuration.JsonПовторите попытку, выбрав версию 2.2.0 или более позднюю.
Добавление сведений о службе Когнитивного поиска Azure
В обозревателе решений щелкните проект правой кнопкой мыши и выберите "Добавить>новый элемент".
В разделе "Добавление нового элемента" найдите "JSON", чтобы вернуть список типов элементов, связанных с JSON.
Выберите JSON-файл, назовите файл "appsettings.json" и нажмите кнопку "Добавить".
Добавьте файл в выходной каталог. Щелкните правой кнопкой мыши appsettings.json и выберите пункт "Свойства". В параметре "Копировать в выходной каталог" выберите "Копировать, если новее".
Скопируйте следующий код JSON в новый JSON-файл.
{ "SearchServiceName": "<YOUR-SEARCH-SERVICE-NAME>", "SearchServiceAdminApiKey": "<YOUR-ADMIN-API-KEY>", "SearchIndexName": "hotels-quickstart" }Замените имя службы поиска (YOUR-SEARCH-SERVICE-NAME) и ключ API администрирования (YOUR-ADMIN-API-KEY) допустимыми значениями. Если конечная точка службы имеет значение
https://mydemo.search.windows.net, имя службы будет "mydemo".
Добавьте файлы класса ".Method" в ваш проект
Этот шаг необходим для создания значимых выходных данных в консоли. При печати результатов в окне консоли отдельные поля из объекта Hotel должны быть возвращены в виде строк. Этот шаг реализует ToString() для выполнения этой задачи, которая выполняется путем копирования необходимого кода в два новых файла.
Добавьте в проект два пустых определения классов: Address.Methods.cs, Hotel.Methods.cs
В Address.Methods.cs перезапись содержимого по умолчанию со следующим кодом строки 1–25.
В Hotel.Methods.cs скопируйте строки 1-68.
1. Создание индекса
Индекс отелей состоит из простых и сложных полей, в которых простое поле " HotelName" или "Описание", а сложные поля — адрес с подполями или коллекция номеров. Если индекс включает сложные типы, изолируйте определения сложных полей в отдельных классах.
Добавьте в проект два пустых определения классов: Address.cs, Hotel.cs
В Address.cs перезаписать содержимое по умолчанию следующим кодом:
using System; using Microsoft.Azure.Search; using Microsoft.Azure.Search.Models; using Newtonsoft.Json; namespace AzureSearchQuickstart { public partial class Address { [IsSearchable] public string StreetAddress { get; set; } [IsSearchable, IsFilterable, IsSortable, IsFacetable] public string City { get; set; } [IsSearchable, IsFilterable, IsSortable, IsFacetable] public string StateProvince { get; set; } [IsSearchable, IsFilterable, IsSortable, IsFacetable] public string PostalCode { get; set; } [IsSearchable, IsFilterable, IsSortable, IsFacetable] public string Country { get; set; } } }В Hotel.cs класс определяет общую структуру индекса, включая ссылки на класс адресов.
namespace AzureSearchQuickstart { using System; using Microsoft.Azure.Search; using Microsoft.Azure.Search.Models; using Newtonsoft.Json; public partial class Hotel { [System.ComponentModel.DataAnnotations.Key] [IsFilterable] public string HotelId { get; set; } [IsSearchable, IsSortable] public string HotelName { get; set; } [IsSearchable] [Analyzer(AnalyzerName.AsString.EnMicrosoft)] public string Description { get; set; } [IsSearchable] [Analyzer(AnalyzerName.AsString.FrLucene)] [JsonProperty("Description_fr")] public string DescriptionFr { get; set; } [IsSearchable, IsFilterable, IsSortable, IsFacetable] public string Category { get; set; } [IsSearchable, IsFilterable, IsFacetable] public string[] Tags { get; set; } [IsFilterable, IsSortable, IsFacetable] public bool? ParkingIncluded { get; set; } [IsFilterable, IsSortable, IsFacetable] public DateTimeOffset? LastRenovationDate { get; set; } [IsFilterable, IsSortable, IsFacetable] public double? Rating { get; set; } public Address Address { get; set; } } }Атрибуты в поле определяют, как оно используется в приложении. Например,
IsSearchableатрибут должен быть назначен каждому полю, которое должно быть включено в полнотекстовый поиск.Замечание
В пакете SDK для .NET поля должны быть явно атрибутами , как
IsSearchable,IsFilterableиIsFacetableIsSortable. Это поведение отличается от REST API, который неявно обеспечивает присвоение на основе типа данных (например, простые строковые поля автоматически выполняют поиск).Точно одно поле в индексе типа
stringдолжно быть ключевым полем, уникальным образом идентифицируя каждый документ. В этой схеме ключ имеет значениеHotelId.В этом индексе поля описания используют необязательное
analyzerсвойство, указанное при переопределении стандартного анализатора Lucene по умолчанию. Полеdescription_frиспользует французский анализатор Lucene (FrLucene), так как он хранит французский текст. Используетсяdescriptionнеобязательный анализатор языка Майкрософт (EnMicrosoft).В Program.cs создайте экземпляр
SearchServiceClientкласса для подключения к службе, используя значения, хранящиеся в файле конфигурации приложения (appsettings.json).SearchServiceClientIndexesимеет свойство, предоставляя все методы, необходимые для создания, перечисления, обновления или удаления индексов Когнитивного поиска Azure.using System; using System.Linq; using System.Threading; using Microsoft.Azure.Search; using Microsoft.Azure.Search.Models; using Microsoft.Extensions.Configuration; namespace AzureSearchQuickstart { class Program { // Demonstrates index delete, create, load, and query // Commented-out code is uncommented in later steps static void Main(string[] args) { IConfigurationBuilder builder = new ConfigurationBuilder().AddJsonFile("appsettings.json"); IConfigurationRoot configuration = builder.Build(); SearchServiceClient serviceClient = CreateSearchServiceClient(configuration); string indexName = configuration["SearchIndexName"]; Console.WriteLine("{0}", "Deleting index...\n"); DeleteIndexIfExists(indexName, serviceClient); Console.WriteLine("{0}", "Creating index...\n"); CreateIndex(indexName, serviceClient); // Uncomment next 3 lines in "2 - Load documents" // ISearchIndexClient indexClient = serviceClient.Indexes.GetClient(indexName); // Console.WriteLine("{0}", "Uploading documents...\n"); // UploadDocuments(indexClient); // Uncomment next 2 lines in "3 - Search an index" // Console.WriteLine("{0}", "Searching index...\n"); // RunQueries(indexClient); Console.WriteLine("{0}", "Complete. Press any key to end application...\n"); Console.ReadKey(); } // Create the search service client private static SearchServiceClient CreateSearchServiceClient(IConfigurationRoot configuration) { string searchServiceName = configuration["SearchServiceName"]; string adminApiKey = configuration["SearchServiceAdminApiKey"]; SearchServiceClient serviceClient = new SearchServiceClient(searchServiceName, new SearchCredentials(adminApiKey)); return serviceClient; } // Delete an existing index to reuse its name private static void DeleteIndexIfExists(string indexName, SearchServiceClient serviceClient) { if (serviceClient.Indexes.Exists(indexName)) { serviceClient.Indexes.Delete(indexName); } } // Create an index whose fields correspond to the properties of the Hotel class. // The Address property of Hotel will be modeled as a complex field. // The properties of the Address class in turn correspond to sub-fields of the Address complex field. // The fields of the index are defined by calling the FieldBuilder.BuildForType() method. private static void CreateIndex(string indexName, SearchServiceClient serviceClient) { var definition = new Microsoft.Azure.Search.Models.Index() { Name = indexName, Fields = FieldBuilder.BuildForType<Hotel>() }; serviceClient.Indexes.Create(definition); } } }По возможности поделитесь одним экземпляром приложения, чтобы избежать открытия слишком большого
SearchServiceClientколичества подключений. Методы классов являются потокобезопасны для обеспечения такого общего доступа.Класс имеет несколько конструкторов. Тот, который требуется, принимает имя службы поиска и
SearchCredentialsобъект в качестве параметров.SearchCredentialsупаковывает ключ API.В определении индекса проще всего создать
Fieldобъекты путем вызоваFieldBuilder.BuildForTypeметода, передав класс модели для параметра типа. Класс модели имеет свойства, которые сопоставляют поля индекса. Это сопоставление позволяет привязать документы из индекса поиска к экземплярам класса модели.Замечание
Если вы не планируете использовать класс модели, вы по-прежнему можете определить индекс, создав
Fieldобъекты напрямую. Имя поля конструктору можно указать вместе с типом данных (или анализатором строковых полей). Вы также можете задать другие свойства, напримерIsSearchable,IsFilterableчтобы указать несколько имен.Нажмите клавишу F5, чтобы создать приложение и создать индекс.
Если проект успешно построен, откроется окно консоли, записыв сообщения о состоянии на экран для удаления и создания индекса.
2. Загрузка документов
В Когнитивном поиске Azure документы — это структуры данных, которые являются входными данными для индексирования и выходных данных из запросов. Полученные из внешнего источника данных входные документы могут быть строками в базе данных, BLOB-объектами в хранилище BLOB или документами JSON на диске. В нашем примере мы выбрали самый простой путь, внедрив прямо в код документы JSON с информацией о четырех отелях.
При отправке документов необходимо использовать IndexBatch объект. Элемент IndexBatch содержит коллекцию объектов IndexAction, каждый из которых включает документ и свойство, указывающее Когнитивному поиску Azure, какое действие выполнить (отправка, слияние, удаление и слияние или загрузка).
В Program.cs создайте массив документов и действий индекса, а затем передайте массив
IndexBatchв . Приведенные ниже документы соответствуют индексу быстрого запуска отеля, как определено классами отелей и адресов.// Upload documents as a batch private static void UploadDocuments(ISearchIndexClient indexClient) { var actions = new IndexAction<Hotel>[] { IndexAction.Upload( new Hotel() { HotelId = "1", HotelName = "Secret Point Motel", Description = "The hotel is ideally located on the main commercial artery of the city in the heart of New York. A few minutes away is Time's 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.", DescriptionFr = "L'hôtel est idéalement situé sur la principale artère commerciale de la ville en plein cœur de New York. A quelques minutes se trouve la place du temps et le centre historique de la ville, ainsi que d'autres lieux d'intérêt qui font de New York l'une des villes les plus attractives et cosmopolites de l'Amérique.", Category = "Boutique", Tags = new[] { "pool", "air conditioning", "concierge" }, ParkingIncluded = false, LastRenovationDate = new DateTimeOffset(1970, 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" } } ), IndexAction.Upload( new Hotel() { HotelId = "2", HotelName = "Twin Dome Motel", Description = "The hotel is situated in a nineteenth century plaza, which has been expanded and renovated to the highest architectural standards to create a modern, functional and first-class hotel in which art and unique historical elements coexist with the most modern comforts.", DescriptionFr = "L'hôtel est situé dans une place du XIXe siècle, qui a été agrandie et rénovée aux plus hautes normes architecturales pour créer un hôtel moderne, fonctionnel et de première classe dans lequel l'art et les éléments historiques uniques coexistent avec le confort le plus moderne.", Category = "Boutique", Tags = new[] { "pool", "free wifi", "concierge" }, ParkingIncluded = false, LastRenovationDate = new DateTimeOffset(1979, 2, 18, 0, 0, 0, TimeSpan.Zero), Rating = 3.60, Address = new Address() { StreetAddress = "140 University Town Center Dr", City = "Sarasota", StateProvince = "FL", PostalCode = "34243", Country = "USA" } } ), IndexAction.Upload( new Hotel() { HotelId = "3", HotelName = "Triple Landscape Hotel", Description = "The Hotel stands out for its gastronomic excellence under the management of William Dough, who advises on and oversees all of the Hotel’s restaurant services.", DescriptionFr = "L'hôtel est situé dans une place du XIXe siècle, qui a été agrandie et rénovée aux plus hautes normes architecturales pour créer un hôtel moderne, fonctionnel et de première classe dans lequel l'art et les éléments historiques uniques coexistent avec le confort le plus moderne.", Category = "Resort and Spa", Tags = new[] { "air conditioning", "bar", "continental breakfast" }, ParkingIncluded = true, LastRenovationDate = new DateTimeOffset(2015, 9, 20, 0, 0, 0, TimeSpan.Zero), Rating = 4.80, Address = new Address() { StreetAddress = "3393 Peachtree Rd", City = "Atlanta", StateProvince = "GA", PostalCode = "30326", Country = "USA" } } ), IndexAction.Upload( new Hotel() { HotelId = "4", HotelName = "Sublime Cliff Hotel", Description = "Sublime Cliff Hotel is located in the heart of the historic center of Sublime in an extremely vibrant and lively area within short walking distance to the sites and landmarks of the city and is surrounded by the extraordinary beauty of churches, buildings, shops and monuments. Sublime Cliff is part of a lovingly restored 1800 palace.", DescriptionFr = "Le sublime Cliff Hotel est situé au coeur du centre historique de sublime dans un quartier extrêmement animé et vivant, à courte distance de marche des sites et monuments de la ville et est entouré par l'extraordinaire beauté des églises, des bâtiments, des commerces et Monuments. Sublime Cliff fait partie d'un Palace 1800 restauré avec amour.", Category = "Boutique", Tags = new[] { "concierge", "view", "24-hour front desk service" }, ParkingIncluded = true, LastRenovationDate = new DateTimeOffset(1960, 2, 06, 0, 0, 0, TimeSpan.Zero), Rating = 4.6, Address = new Address() { StreetAddress = "7400 San Pedro Ave", City = "San Antonio", StateProvince = "TX", PostalCode = "78216", Country = "USA" } } ), }; var batch = IndexBatch.New(actions); try { indexClient.Documents.Index(batch); } catch (IndexBatchException e) { // When a service is under load, indexing might fail for some documents in the batch. // Depending on your application, you can compensate by delaying and retrying. // For this simple demo, we just log the failed document keys and continue. Console.WriteLine( "Failed to index some of the documents: {0}", String.Join(", ", e.IndexingResults.Where(r => !r.Succeeded).Select(r => r.Key))); } // Wait 2 seconds before starting queries Console.WriteLine("Waiting for indexing...\n"); Thread.Sleep(2000); }После инициализации
IndexBatchобъекта его можно отправить в индекс, вызвавDocuments.IndexобъектSearchIndexClient.Documents— это свойствоSearchIndexClient, которое предоставляет методы для добавления, изменения, удаления или запроса документов в индексе.Окружающий
try/catchвызовIndexметода перехватывает ошибки индексирования, которые могут произойти, если служба находится под тяжелой нагрузкой. В рабочем коде можно отложить, а затем повторить индексирование документов, которые завершилось сбоем, или продолжить, как и пример, или обрабатывать его другим способом, который соответствует требованиям согласованности данных приложения.2-секундная задержка дает достаточно времени для асинхронного индексирования, чтобы все документы уже были проиндексированы перед выполнением запросов. Задержки в коде обычно используются только в демонстрациях, тестах и примерах приложений.
В Program.cs, в main, раскомментируйте строки "2 – загрузка документов".
// Uncomment next 3 lines in "2 - Load documents" ISearchIndexClient indexClient = serviceClient.Indexes.GetClient(indexName); Console.WriteLine("{0}", "Uploading documents...\n"); UploadDocuments(indexClient);Нажмите клавишу F5, чтобы перестроить приложение.
Если проект успешно выполняется, откроется окно консоли, записывая сообщения о состоянии, на этот раз добавляется сообщение о загрузке документов. На портале Azure на странице Обзор службы поиска индекс hotels-quickstart должен содержать 4 документа.
Дополнительные сведения об обработке документов см. в статье "Как пакет SDK для .NET обрабатывает документы".
3. Поиск индекса
Результаты запросов можно получить сразу по завершении индексирования первого документа, но для полноценного тестирования индекса придется подождать, пока закончится индексирование всех документов.
В этом разделе мы добавим две новые функции: логику запроса и результаты. Для запросов используйте Search метод. Этот метод принимает текст поиска, а также другие параметры.
Класс DocumentsSearchResult представляет результаты.
В Program.cs создайте метод WriteDocuments, который выводит результаты поиска в консоль.
private static void WriteDocuments(DocumentSearchResult<Hotel> searchResults) { foreach (SearchResult<Hotel> result in searchResults.Results) { Console.WriteLine(result.Document); } Console.WriteLine(); }Создайте метод RunQueries для выполнения запросов и возврата результатов. Результаты представляют собой объекты Hotel. Чтобы отобразить отдельные поля, можно использовать параметр выбора. Если поле не входит в параметр select, его соответствующее свойство Hotel будет иметь значение NULL.
private static void RunQueries(ISearchIndexClient indexClient) { SearchParameters parameters; DocumentSearchResult<Hotel> results; // Query 1 Console.WriteLine("Query 1: Search for term 'Atlanta' with no result trimming"); parameters = new SearchParameters(); results = indexClient.Documents.Search<Hotel>("Atlanta", parameters); WriteDocuments(results); // Query 2 Console.WriteLine("Query 2: Search on the term 'Atlanta', with trimming"); Console.WriteLine("Returning only these fields: HotelName, Tags, Address:\n"); parameters = new SearchParameters() { Select = new[] { "HotelName", "Tags", "Address" }, }; results = indexClient.Documents.Search<Hotel>("Atlanta", parameters); WriteDocuments(results); // Query 3 Console.WriteLine("Query 3: Search for the terms 'restaurant' and 'wifi'"); Console.WriteLine("Return only these fields: HotelName, Description, and Tags:\n"); parameters = new SearchParameters() { Select = new[] { "HotelName", "Description", "Tags" } }; results = indexClient.Documents.Search<Hotel>("restaurant, wifi", parameters); WriteDocuments(results); // Query 4 -filtered query Console.WriteLine("Query 4: Filter on ratings greater than 4"); Console.WriteLine("Returning only these fields: HotelName, Rating:\n"); parameters = new SearchParameters() { Filter = "Rating gt 4", Select = new[] { "HotelName", "Rating" } }; results = indexClient.Documents.Search<Hotel>("*", parameters); WriteDocuments(results); // Query 5 - top 2 results Console.WriteLine("Query 5: Search on term 'boutique'"); Console.WriteLine("Sort by rating in descending order, taking the top two results"); Console.WriteLine("Returning only these fields: HotelId, HotelName, Category, Rating:\n"); parameters = new SearchParameters() { OrderBy = new[] { "Rating desc" }, Select = new[] { "HotelId", "HotelName", "Category", "Rating" }, Top = 2 }; results = indexClient.Documents.Search<Hotel>("boutique", parameters); WriteDocuments(results); }Существует два способа сопоставления терминов в запросе: полнотекстовый поиск и фильтры. Полнотекстовый поисковый запрос ищет один или несколько терминов в
IsSearchableполях в индексе. Фильтр — это логическое выражение, вычисляемое поIsFilterableполям в индексе. Вы можете использовать полнотекстовый поиск и фильтры вместе или отдельно.Поиск и фильтры выполняются с помощью
Documents.Searchметода. Запрос поиска можно передать вsearchTextпараметре, а выражение фильтра можно передать вFilterсвойствеSearchParametersкласса. Чтобы отфильтровать без поиска, просто передайте значение"*"для параметраsearchText. Чтобы выполнить поиск без фильтрации, просто оставьтеFilterсвойство неустановленным или вообще не передавайте экземплярSearchParameters.В файле Program.cs в методе main раскомментируйте строки для "3 - Поиск".
// Uncomment next 2 lines in "3 - Search an index" Console.WriteLine("{0}", "Searching documents...\n"); RunQueries(indexClient);Теперь решение завершено. Нажмите клавишу F5, чтобы перестроить приложение и запустить полнофункциональную программу.
Выходные данные включают те же сообщения, что и раньше, с добавлением сведений о запросах и результатах.
Очистите ресурсы
Работая с собственной подпиской, в конце проекта полезно определить, нужны ли вам созданные ресурсы. Оставленные без присмотра ресурсы могут стоить вам денег. Вы можете удалить ресурсы по отдельности или удалить группу ресурсов, чтобы удалить весь набор ресурсов.
Ресурсы на портале можно найти и управлять ими, используя ссылку Все ресурсы или группы ресурсов на панели навигации слева.
Если вы используете бесплатную службу, помните, что вы ограничены тремя индексами, индексаторами и источниками данных. Вы можете удалить отдельные элементы на портале, чтобы остаться в пределах ограничения.
Дальнейшие действия
В этом кратком руководстве по C# вы проработали ряд задач, чтобы создать индекс, загрузить его с документами и запустить запросы. На разных этапах мы шли на уступки, чтобы код было проще читать и понимать. Если вы комфортно с основными понятиями, мы рекомендуем следующую статью для изучения альтернативных подходов и концепций, которые углубит ваши знания.
Примеры кода и индекса являются расширенными версиями данного кода. В следующем примере добавляется коллекция Комнат, используются различные классы и действия, а также более подробно рассматривается процесс обработки.
Хотите оптимизировать и сократить ваши расходы на облако?