Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
В этой статье объясняется, как создавать и управлять объектами поиска с помощью C# и устаревшей клиентской библиотеки Microsoft.Azure.Search (версия 10) в пакете SDK Azure для .NET.
Версия 10 — это последняя версия пакета Microsoft.Azure.Search. Передвигаясь вперед, новые функции будут развернуты в Azure.Search.Documents из команды пакета SDK Azure.
Замечание
Если у вас есть уже начатые или текущие проекты разработки, вы можете продолжать использовать версию 10. Для новых проектов или использования новых функций необходимо перейти в новую библиотеку.
О версии 10
Пакет SDK состоит из нескольких клиентских библиотек, позволяющих управлять индексами, источниками данных, индексаторами и картами синонимов, а также отправлять документы и управлять ими, а также выполнять запросы, не имея необходимости иметь дело с подробными сведениями о HTTP и JSON. Эти клиентские библиотеки распределены как пакеты NuGet.
Основной пакет NuGet — Microsoft.Azure.Searchэто метапакет, который включает все остальные пакеты в качестве зависимостей. Используйте этот пакет, если вы только начинаете работу или знаете, что приложение потребует всех функций Когнитивного поиска Azure.
Другие пакеты NuGet в пакете SDK:
-
Microsoft.Azure.Search.Data: используйте этот пакет, если вы разрабатываете приложение .NET с помощью Когнитивного поиска Azure, и вам нужно только запрашивать или обновлять документы в индексах. Если вам также нужно создать или обновить индексы, словарь синонимов или другие ресурсы, связанные с уровнем сервиса, используйте пакетMicrosoft.Azure.Search. -
Microsoft.Azure.Search.Service: используйте этот пакет, если вы разрабатываете автоматизацию в .NET для управления индексами Когнитивного поиска Azure, картами синонимов, индексаторами, источниками данных или другими ресурсами уровня обслуживания. Если вам нужно запрашивать или обновлять документы в индексах, используйтеMicrosoft.Azure.Search.Dataпакет. Если вам нужны все функциональные возможности Когнитивного поиска Azure, используйтеMicrosoft.Azure.Searchэтот пакет. -
Microsoft.Azure.Search.Common: распространенные типы, необходимые библиотекам .NET когнитивного поиска Azure. Этот пакет не требуется использовать непосредственно в приложении. Оно предназначено только для использования в качестве зависимости.
Различные клиентские библиотеки определяют такие классы, как Index, Fieldи Document, а также операции, такие Indexes.Create как и Documents.SearchSearchServiceClient классы и SearchIndexClient классы. Эти классы упорядочены в следующие подразделы:
Если вы хотите предоставить отзыв о будущем обновлении пакета SDK, ознакомьтесь со страницей отзывов или создайте проблему на сайте GitHub и укажите "Когнитивный поиск Azure" в заголовке проблемы.
Пакет SDK для .NET предназначен для версии2019-05-06 REST API Когнитивного поиска Azure. Эта версия включает поддержку сложных типов, обогащения ИИ, автозаполнения и режима синтаксического анализа JsonLines при индексировании BLOB-объектов Azure.
Этот пакет SDK не поддерживает такие операции управления , как создание и масштабирование служб поиска и управление ключами API. Если вам нужно управлять ресурсами поиска из приложения .NET, можно использовать пакет SDK для управления .NET для Когнитивного поиска Azure.
Обновление до версии 10
Если вы уже используете более раннюю версию пакета SDK для .NET для Когнитивного поиска Azure и хотите обновить до последней общедоступной версии, в этой статье объясняется, как это сделать.
Требования к пакету SDK
- Visual Studio 2017 или более поздней версии.
- Ваша собственная служба Когнитивного поиска Azure. Чтобы использовать пакет SDK, вам потребуется имя службы и один или несколько ключей API. Создание службы на портале поможет вам выполнить следующие действия.
- Скачайте пакет NuGet для .NET SDK Когнитивного поиска Azure с помощью команды "Управление пакетами NuGet" в Visual Studio. Просто найдите имя
Microsoft.Azure.Searchпакета на NuGet.org (или одно из других имен пакетов выше, если вам требуется только подмножество функций).
Пакет SDK для .NET для Когнитивного поиска Azure поддерживает приложения, предназначенные для .NET Framework 4.5.2 и более поздних версий, а также .NET Core 2.0 и более поздних версий.
Основные сценарии
В приложении поиска необходимо выполнить несколько действий. В этом руководстве мы рассмотрим следующие основные сценарии:
- Создание индекса
- Заполнение индекса документами
- Поиск документов с помощью полнотекстового поиска и фильтров
В следующем примере кода показано каждое из этих сценариев. Вы можете использовать фрагменты кода в собственном приложении.
Обзор
Пример приложения, который мы рассмотрим, создает новый индекс с именем "hotels", заполняет его несколькими документами, а затем выполняет некоторые поисковые запросы. Ниже приведена основная программа, показывающая общий поток:
// This sample shows how to delete, create, upload documents and query an index
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);
ISearchIndexClient indexClient = serviceClient.Indexes.GetClient(indexName);
Console.WriteLine("{0}", "Uploading documents...\n");
UploadDocuments(indexClient);
ISearchIndexClient indexClientForQueries = CreateSearchIndexClient(configuration);
RunQueries(indexClientForQueries);
Console.WriteLine("{0}", "Complete. Press any key to end application...\n");
Console.ReadKey();
}
Замечание
Полный исходный код примера приложения, используемого в этом пошаговом руководстве, можно найти на GitHub.
Мы рассмотрим этот шаг по шагу. Сначала необходимо создать новый SearchServiceClient. Этот объект позволяет управлять индексами. Чтобы создать ее, необходимо указать имя службы Когнитивного поиска Azure, а также ключ API администратора. Эти сведения можно ввести в appsettings.json файле примера приложения.
private static SearchServiceClient CreateSearchServiceClient(IConfigurationRoot configuration)
{
string searchServiceName = configuration["SearchServiceName"];
string adminApiKey = configuration["SearchServiceAdminApiKey"];
SearchServiceClient serviceClient = new SearchServiceClient(searchServiceName, new SearchCredentials(adminApiKey));
return serviceClient;
}
Замечание
Если вы указали неправильный ключ (например, ключ запроса, в котором был необходим ключ администратора), SearchServiceClient при первом вызове метода операции вызовет CloudException сообщение об ошибке "Запрещено" при первом вызове метода операции, например Indexes.Create. Если это произойдет с вами, дважды проверьте ключ API.
Следующие несколько строк вызывают методы для создания индекса с именем "hotels", удалив его сначала, если он уже существует. Мы рассмотрим эти методы немного позже.
Console.WriteLine("{0}", "Deleting index...\n");
DeleteIndexIfExists(indexName, serviceClient);
Console.WriteLine("{0}", "Creating index...\n");
CreateIndex(indexName, serviceClient);
Затем необходимо заполнить индекс. Для заполнения индекса нам потребуется SearchIndexClient. Существует два способа получить его: путем создания или вызова Indexes.GetClient на SearchServiceClient. Мы используем последний для удобства.
ISearchIndexClient indexClient = serviceClient.Indexes.GetClient(indexName);
Замечание
В обычном приложении поиска управление индексами и населением может обрабатываться отдельным компонентом из поисковых запросов.
Indexes.GetClient удобно заполнять индекс, так как он избавляет вас от необходимости введения дополнительных SearchCredentials. Это делается путем передачи ключа администратора, который вы использовали для создания SearchServiceClient, новому SearchIndexClient. Однако в части приложения, выполняющего запросы, лучше создать SearchIndexClient непосредственно, чтобы передать ключ запроса, который позволяет только считывать данные, а не ключ администратора. Это соответствует принципу наименьших привилегий и поможет сделать приложение более безопасным. Дополнительные сведения о ключах администратора и ключах запросов см. здесь.
Теперь, когда у нас есть SearchIndexClient, мы можем заполнить индекс. Популяция индексов выполняется другим методом, который мы рассмотрим позже.
Console.WriteLine("{0}", "Uploading documents...\n");
UploadDocuments(indexClient);
Наконец, мы выполняем несколько поисковых запросов и отображаем результаты. На этот раз мы используем другой SearchIndexClient:
ISearchIndexClient indexClientForQueries = CreateSearchIndexClient(indexName, configuration);
RunQueries(indexClientForQueries);
Далее мы рассмотрим RunQueries метод. Ниже приведен код для создания нового SearchIndexClient:
private static SearchIndexClient CreateSearchIndexClient(string indexName, IConfigurationRoot configuration)
{
string searchServiceName = configuration["SearchServiceName"];
string queryApiKey = configuration["SearchServiceQueryApiKey"];
SearchIndexClient indexClient = new SearchIndexClient(searchServiceName, indexName, new SearchCredentials(queryApiKey));
return indexClient;
}
На этот раз мы используем ключ запроса, так как нам не нужен доступ на запись к индексу. Эти сведения можно ввести в appsettings.json файле примера приложения.
Если запустить это приложение с допустимым именем службы и ключами API, выходные данные должны выглядеть следующим образом: (Некоторые выходные данные консоли заменены на "..." в целях иллюстрации.)
Deleting index...
Creating index...
Uploading documents...
Waiting for documents to be indexed...
Search the entire index for the term 'motel' and return only the HotelName field:
Name: Secret Point Motel
Name: Twin Dome Motel
Apply a filter to the index to find hotels with a room cheaper than $100 per night, and return the hotelId and description:
HotelId: 1
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 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.
HotelId: 2
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.
Search the entire index, order by a specific field (lastRenovationDate) in descending order, take the top two results, and show only hotelName and lastRenovationDate:
Name: Triple Landscape Hotel
Last renovated on: 9/20/2015 12:00:00 AM +00:00
Name: Twin Dome Motel
Last renovated on: 2/18/1979 12:00:00 AM +00:00
Search the hotel names for the term 'hotel':
HotelId: 3
Name: Triple Landscape Hotel
...
Complete. Press any key to end application...
Полный исходный код приложения представлен в конце этой статьи.
Далее мы рассмотрим каждый из методов, вызываемых Main.
Создание индекса
После создания SearchServiceClientMain удаляет индекс "hotels", если он уже существует. Это удаление выполняется следующим методом:
private static void DeleteIndexIfExists(string indexName, SearchServiceClient serviceClient)
{
if (serviceClient.Indexes.Exists(indexName))
{
serviceClient.Indexes.Delete(indexName);
}
}
Этот метод использует указанный SearchServiceClient для проверки наличия индекса и, если он существует, удаляет его.
Замечание
Пример кода в этой статье использует синхронные методы пакета программного обеспечения разработки (SDK) .NET для Когнитивного поиска Azure в целях упрощения. Рекомендуется использовать асинхронные методы в собственных приложениях, чтобы обеспечить их масштабируемость и реагирование. Например, в приведенном выше методе можно использовать ExistsAsync и DeleteAsync вместо Exists и Delete.
Затем создадим новый индекс "hotels", Main вызвав этот метод:
private static void CreateIndex(string indexName, SearchServiceClient serviceClient)
{
var definition = new Index()
{
Name = indexName,
Fields = FieldBuilder.BuildForType<Hotel>()
};
serviceClient.Indexes.Create(definition);
}
Этот метод создает новый Index объект со списком объектов, определяющих Field схему нового индекса. Каждое поле имеет имя, тип данных и несколько атрибутов, которые определяют его поведение при поиске. Класс FieldBuilder использует отражение, чтобы создать список объектов Field для соответствующего индекса. Он проверяет общедоступные свойства и атрибуты полученного класса модели Hotel. Класс Hotel мы рассмотрим подробно позже.
Замечание
При необходимости вы всегда можете создать список объектов Field напрямую, а не с помощью FieldBuilder. Например, вы не хотите использовать класс модели или вам может потребоваться использовать существующий класс модели, который не требуется изменять путем добавления атрибутов.
В дополнение к полям можно также добавлять профили оценки, предложения или CORS в индекс (эти параметры опущены из примера для краткости). Дополнительные сведения об объекте Index и его составных частях см. в справочнике по пакету SDK, а также в справочнике по REST API когнитивного поиска Azure.
Заполнение индекса
Следующим шагом будет заполнение Main, только что созданного индекса. Эта популяция индекса выполняется в следующем методе: (Некоторый код заменен на "..." в целях иллюстрации. Полный пример решения для полного кода заполнения данных.)
private static void UploadDocuments(ISearchIndexClient indexClient)
{
var hotels = new Hotel[]
{
new Hotel()
{
HotelId = "1",
HotelName = "Secret Point Motel",
...
Address = new Address()
{
StreetAddress = "677 5th Ave",
...
},
Rooms = new Room[]
{
new Room()
{
Description = "Budget Room, 1 Queen Bed (Cityside)",
...
},
new Room()
{
Description = "Budget Room, 1 King Bed (Mountain View)",
...
},
new Room()
{
Description = "Deluxe Room, 2 Double Beds (City View)",
...
}
}
},
new Hotel()
{
HotelId = "2",
HotelName = "Twin Dome Motel",
...
{
StreetAddress = "140 University Town Center Dr",
...
},
Rooms = new Room[]
{
new Room()
{
Description = "Suite, 2 Double Beds (Mountain View)",
...
},
new Room()
{
Description = "Standard Room, 1 Queen Bed (City View)",
...
},
new Room()
{
Description = "Budget Room, 1 King Bed (Waterfront View)",
...
}
}
},
new Hotel()
{
HotelId = "3",
HotelName = "Triple Landscape Hotel",
...
Address = new Address()
{
StreetAddress = "3393 Peachtree Rd",
...
},
Rooms = new Room[]
{
new Room()
{
Description = "Standard Room, 2 Queen Beds (Amenities)",
...
},
new Room ()
{
Description = "Standard Room, 2 Double Beds (Waterfront View)",
...
},
new Room()
{
Description = "Deluxe Room, 2 Double Beds (Cityside)",
...
}
}
}
};
var batch = IndexBatch.Upload(hotels);
try
{
indexClient.Documents.Index(batch);
}
catch (IndexBatchException e)
{
// Sometimes when your Search service is under load, indexing will fail for some of the documents in
// the batch. Depending on your application, you can take compensating actions like 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)));
}
Console.WriteLine("Waiting for documents to be indexed...\n");
Thread.Sleep(2000);
}
Этот метод состоит из четырех частей. Первый создает массив из 3 Hotel объектов, каждый из которых содержит 3 Room объекта, которые будут служить входными данными для отправки в индекс. Эти данные жестко запрограммированы для простоты. В собственном приложении данные, скорее всего, будут поступать из внешнего источника данных, например базы данных SQL.
Вторая часть создает IndexBatch, содержащую документы. Вы указываете операцию, которую необходимо применить к пакету во время его создания, в данном случае путем вызова метода IndexBatch.Upload. Затем пакет отправляется в индекс Когнитивного поиска Azure с помощью Documents.Index метода.
Замечание
В этом примере мы просто отправляем документы. Если требуется внести изменения в существующие документы или удалить документы, можно создать пакеты, вызвав методы IndexBatch.Merge, IndexBatch.MergeOrUpload или IndexBatch.Delete. Вы также можете комбинировать различные операции в одном пакете, вызвав IndexBatch.New, который принимает коллекцию объектов IndexAction, каждый из которых указывает Azure Cognitive Search выполнить конкретную операцию над документом. Можно создать каждый IndexAction с отдельной операцией, вызвав соответствующий метод, например IndexAction.Merge, IndexAction.Upload и т. д.
Третья часть метода — это блок catch, который обрабатывает важные ошибки индексирования. Если служба Когнитивного поиска Azure не сможет индексировать некоторые документы в пакете, будет выброшено IndexBatchException, вызываемое Documents.Index. Это исключение может произойти, если вы индексируете документы, пока служба находится под тяжелой нагрузкой. Мы настоятельно рекомендуем явным образом обрабатывать этот случай в вашем коде. Вы можете задержать и повторить попытку индексирования соответствующих документов либо занести ошибку в журнал и продолжить работу, как в нашем примере, а также выполнить другие действия в зависимости от требований вашего приложения к целостности данных.
Замечание
Метод FindFailedActionsToRetry можно использовать для создания нового пакета, содержащего только те действия, которые завершились сбоем в предыдущем вызове Index. Существует обсуждение того, как правильно использовать его в StackOverflow.
И наконец, метод UploadDocuments вызывает задержку на две секунды. Индексирование выполняется асинхронно в службе Когнитивного поиска Azure, поэтому пример приложения должен подождать некоторое время, чтобы убедиться, что документы доступны для поиска. Такие задержки обычно необходимы только в демонстрациях, тестах и примерах приложений.
Как пакет SDK для .NET обрабатывает документы
Возможно, вам интересно, как пакет SDK для .NET для Когнитивного поиска Azure может отправлять экземпляры определяемого пользователем класса, например Hotel в индекс. Чтобы ответить на этот вопрос, давайте рассмотрим Hotel класс:
using System;
using Microsoft.Azure.Search;
using Microsoft.Azure.Search.Models;
using Microsoft.Spatial;
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.EnLucene)]
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; }
// SmokingAllowed reflects whether any room in the hotel allows smoking.
// The JsonIgnore attribute indicates that a field should not be created
// in the index for this property and it will only be used by code in the client.
[JsonIgnore]
public bool? SmokingAllowed => (Rooms != null) ? Array.Exists(Rooms, element => element.SmokingAllowed == true) : (bool?)null;
[IsFilterable, IsSortable, IsFacetable]
public DateTimeOffset? LastRenovationDate { get; set; }
[IsFilterable, IsSortable, IsFacetable]
public double? Rating { get; set; }
public Address Address { get; set; }
[IsFilterable, IsSortable]
public GeographyPoint Location { get; set; }
public Room[] Rooms { get; set; }
}
Первое, что следует заметить, что имя каждого общедоступного свойства в Hotel классе сопоставляется с полем с тем же именем в определении индекса. Если вы хотите, чтобы каждое поле начиналось с маленькой буквы ("camelCase"), вы можете указать пакету SDK автоматически сопоставить имена свойств с camelCase с помощью атрибута [SerializePropertyNamesAsCamelCase] в классе. Этот сценарий распространен в приложениях .NET, которые выполняют привязку данных, когда целевая схема находится вне контроля разработчика приложения, без необходимости нарушать правила именования в стиле Pascal в .NET.
Замечание
SDK для Когнитивного поиска Azure на платформе .NET использует библиотеку NewtonSoft JSON.NET для сериализации и десериализации пользовательских объектов модели в JSON и обратно. При необходимости эту сериализацию можно настроить. Дополнительные сведения см. в разделе "Настраиваемая сериализация" с JSON.NET.
Во-вторых, каждое свойство украшено такими атрибутами, как IsFilterable, IsSearchable, Keyи Analyzer. Эти атрибуты непосредственно соответствуют атрибутам полей в индексе Azure Cognitive Search. Класс FieldBuilder на основе этих свойств создает определения полей для индекса.
Третье важное значение для Hotel класса — это типы данных общедоступных свойств. Типы .NET этих свойств соответствуют эквивалентным типам полей в определении индекса. Например, свойство строки Category сопоставляется с полем category, которое имеет тип Edm.String. Аналогичные сопоставления присутствуют между типами bool?, Edm.Boolean, DateTimeOffset?, Edm.DateTimeOffset и т. д. Конкретные правила сопоставления типов документированы методом Documents.Get в справочнике SDK .NET для Azure Cognitive Search. Класс FieldBuilder заботится об этом сопоставлении, но всё же полезно понять, если вам нужно решить любые проблемы сериализации.
Вы заметили свойство SmokingAllowed?
[JsonIgnore]
public bool? SmokingAllowed => (Rooms != null) ? Array.Exists(Rooms, element => element.SmokingAllowed == true) : (bool?)null;
Атрибут JsonIgnore в этом свойстве указывает для FieldBuilder, что его не следует сериализовать в индекс в качестве поля. Это отличный способ создать клиентские вычисляемые свойства, которые можно использовать в качестве вспомогательных в приложении. В этом случае свойство SmokingAllowed отражает, разрешено ли курение в любом Room в коллекции Rooms. Если все являются ложными, это означает, что весь отель не разрешает курить.
Некоторые свойства, такие как Address и Rooms являются экземплярами классов .NET. Эти свойства представляют более сложные структуры данных и, в результате, требуются поля с сложным типом данных в индексе.
Свойство Address представляет набор нескольких значений в Address классе, определенных ниже:
using System;
using Microsoft.Azure.Search;
using Microsoft.Azure.Search.Models;
using Newtonsoft.Json;
namespace AzureSearch.SDKHowTo
{
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; }
}
}
Этот класс содержит стандартные значения, используемые для описания адресов в США или Канаде. Такие типы можно использовать для группировки логических полей в индексе.
Свойство Rooms представляет массив Room объектов:
using System;
using Microsoft.Azure.Search;
using Microsoft.Azure.Search.Models;
using Newtonsoft.Json;
namespace AzureSearch.SDKHowTo
{
public partial class Room
{
[IsSearchable]
[Analyzer(AnalyzerName.AsString.EnMicrosoft)]
public string Description { get; set; }
[IsSearchable]
[Analyzer(AnalyzerName.AsString.FrMicrosoft)]
[JsonProperty("Description_fr")]
public string DescriptionFr { get; set; }
[IsSearchable, IsFilterable, IsFacetable]
public string Type { get; set; }
[IsFilterable, IsFacetable]
public double? BaseRate { get; set; }
[IsSearchable, IsFilterable, IsFacetable]
public string BedOptions { get; set; }
[IsFilterable, IsFacetable]
public int SleepsCount { get; set; }
[IsFilterable, IsFacetable]
public bool? SmokingAllowed { get; set; }
[IsSearchable, IsFilterable, IsFacetable]
public string[] Tags { get; set; }
}
}
Ваша модель данных в .NET и соответствующая схема индексации должны быть разработаны таким образом, чтобы поддерживать поисковый опыт, который вы хотите предоставить конечному пользователю. Каждый объект верхнего уровня в .NET, т. е. документ в индексе, соответствует результату поиска, который будет представлен в пользовательском интерфейсе. Например, в приложении поиска отеля конечным пользователям может потребоваться выполнить поиск по имени отеля, функциям отеля или характеристикам конкретного номера. Мы рассмотрим некоторые примеры запросов немного позже.
Эта возможность использовать собственные классы для взаимодействия с документами в индексе работает в обоих направлениях: вы также можете получать результаты поиска и позволять SDK автоматически десериализовать их в выбранный вами тип, как мы увидим в следующем разделе.
Замечание
Пакет SDK для .NET для Когнитивного поиска Azure также поддерживает динамически типизированные документы с помощью Document класса, который является сопоставлением ключей и значений имен полей со значениями полей. Это полезно в сценариях, когда вы не знаете схему индекса во время разработки или где было бы неудобно привязать к определенным классам моделей. Все методы в пакете SDK, которые имеют дело с документами, имеют перегрузки, которые работают с Document классом, а также строго типизированные перегрузки, которые принимают параметр универсального типа. В этом руководстве используются только последние в примере кода.
КлассDocument наследует от Dictionary<string, object>.
Почему следует использовать типы данных, допускающие значение NULL
При разработке собственных классов моделей для сопоставления с индексом Когнитивного поиска Azure рекомендуется объявлять свойства типов значений, таких как bool и int быть пустыми (например, bool? вместо bool). Если вы используете ненулевое свойство, необходимо гарантировать , что документы в индексе не содержат значение NULL для соответствующего поля. Ни пакет SDK, ни служба Когнитивного поиска Azure не помогут вам применить это.
Это не просто гипотетическая проблема: представьте сценарий, в котором вы добавляете новое поле в существующий индекс, имеющий тип Edm.Int32. После обновления определения индекса все документы будут иметь значение NULL для этого нового поля (так как все типы имеют значение NULL в Когнитивном поиске Azure). Если вы используете класс модели с свойством, не допускающим значение NULL, int для этого поля, вы получите JsonSerializationException, как при попытке получить документы:
Error converting value {null} to type 'System.Int32'. Path 'IntValue'.
По этой причине рекомендуется использовать типы, допускающие значение NULL, в классах моделей в качестве рекомендации.
Настраиваемая сериализация с помощью JSON.NET
Пакет SDK использует JSON.NET для сериализации и десериализации документов. При необходимости можно настроить сериализацию и десериализацию, определив собственный JsonConverter или IContractResolver. Дополнительные сведения см. в документации по JSON.NET. Это может быть полезно, если вы хотите адаптировать существующий класс модели из приложения для использования с Когнитивным поиском Azure и другими более сложными сценариями. Например, с настраиваемой сериализацией можно:
- Включите или исключите определенные свойства класса модели из хранения в виде полей документа.
- Сопоставляйте имена свойств в коде и именах полей в индексе.
- Создайте настраиваемые атрибуты, которые можно использовать для сопоставления свойств с полями документа.
Примеры реализации пользовательской сериализации можно найти в модульных тестах Azure Cognitive Search .NET SDK на сайте GitHub. Хорошая отправная точка — это папка. Он содержит классы, используемые пользовательскими тестами сериализации.
Поиск документов в индексе
Последний шаг в примере приложения — поиск некоторых документов в индексе:
private static void RunQueries(ISearchIndexClient indexClient)
{
SearchParameters parameters;
DocumentSearchResult<Hotel> results;
Console.WriteLine("Search the entire index for the term 'motel' and return only the HotelName field:\n");
parameters =
new SearchParameters()
{
Select = new[] { "HotelName" }
};
results = indexClient.Documents.Search<Hotel>("motel", parameters);
WriteDocuments(results);
Console.Write("Apply a filter to the index to find hotels with a room cheaper than $100 per night, ");
Console.WriteLine("and return the hotelId and description:\n");
parameters =
new SearchParameters()
{
Filter = "Rooms/any(r: r/BaseRate lt 100)",
Select = new[] { "HotelId", "Description" }
};
results = indexClient.Documents.Search<Hotel>("*", parameters);
WriteDocuments(results);
Console.Write("Search the entire index, order by a specific field (lastRenovationDate) ");
Console.Write("in descending order, take the top two results, and show only hotelName and ");
Console.WriteLine("lastRenovationDate:\n");
parameters =
new SearchParameters()
{
OrderBy = new[] { "LastRenovationDate desc" },
Select = new[] { "HotelName", "LastRenovationDate" },
Top = 2
};
results = indexClient.Documents.Search<Hotel>("*", parameters);
WriteDocuments(results);
Console.WriteLine("Search the entire index for the term 'hotel':\n");
parameters = new SearchParameters();
results = indexClient.Documents.Search<Hotel>("hotel", parameters);
WriteDocuments(results);
}
При каждом выполнении запроса этот метод сначала создает новый SearchParameters объект. Этот объект позволяет задать дополнительные параметры запроса, например сортировку, фильтрацию, разбиение на страницы и фасетизацию. В этом методе мы устанавливаем свойства Filter, Select, OrderBy и Top для разных запросов.
SearchParameters Все свойства описаны здесь.
Следующий шаг — фактически выполнить поисковый запрос. Выполнение поиска выполняется с помощью метода Documents.Search. Для каждого запроса мы передаем текст поиска в качестве строки (или "*" если нет текста поиска), а также параметры поиска, созданные ранее. Мы также указываем Hotel как параметр типа Documents.Search, что сообщает пакету SDK десериализовать документы в результатах поиска в объекты типа Hotel.
Замечание
Дополнительные сведения о синтаксисе выражения поискового запроса см. здесь.
Наконец, после каждого запроса этот метод выполняет итерацию всех совпадений в результатах поиска, печатая каждый документ в консоли:
private static void WriteDocuments(DocumentSearchResult<Hotel> searchResults)
{
foreach (SearchResult<Hotel> result in searchResults.Results)
{
Console.WriteLine(result.Document);
}
Console.WriteLine();
}
Давайте подробнее рассмотрим каждый из запросов. Ниже приведен код для выполнения первого запроса:
parameters =
new SearchParameters()
{
Select = new[] { "HotelName" }
};
results = indexClient.Documents.Search<Hotel>("motel", parameters);
WriteDocuments(results);
В этом случае мы ищем весь индекс слова "мотель" в любом поле поиска, и мы хотим получить только имена отелей, как указано параметром Select . Результаты приведены ниже.
Name: Secret Point Motel
Name: Twin Dome Motel
Следующий запрос немного интереснее. Мы хотим найти отели с комнатой по цене за ночь менее $100 и вернуть только идентификатор отеля и описание.
parameters =
new SearchParameters()
{
Filter = "Rooms/any(r: r/BaseRate lt 100)",
Select = new[] { "HotelId", "Description" }
};
results = indexClient.Documents.Search<Hotel>("*", parameters);
WriteDocuments(results);
Этот запрос использует выражение OData $filterRooms/any(r: r/BaseRate lt 100), чтобы отфильтровать документы в индексе. В этом случае любой оператор используется для применения baseRate lt 100 к каждому элементу в коллекции Комнат. Дополнительные сведения о синтаксисе OData, который поддерживает когнитивный поиск Azure, см. здесь.
Ниже приведены результаты запроса:
HotelId: 1
Description: The hotel is ideally located on the main commercial artery of the city in the heart of New York...
HotelId: 2
Description: The hotel is situated in a nineteenth century plaza, which has been expanded and renovated to...
Далее мы хотим найти первые два отеля, которые были недавно отремонтированы, и показать имя отеля и дату последнего ремонта. Ниже приведен код:
parameters =
new SearchParameters()
{
OrderBy = new[] { "LastRenovationDate desc" },
Select = new[] { "HotelName", "LastRenovationDate" },
Top = 2
};
results = indexClient.Documents.Search<Hotel>("*", parameters);
WriteDocuments(results);
В этом случае мы снова используем синтаксис OData, чтобы указать OrderBy параметр как lastRenovationDate desc. Мы также установили Top равным 2, чтобы мы получали лишь два первых документа. Как и раньше, мы устанавливаем Select , чтобы указать, какие поля должны быть возвращены.
Результаты приведены ниже.
Name: Fancy Stay Last renovated on: 6/27/2010 12:00:00 AM +00:00
Name: Roach Motel Last renovated on: 4/28/1982 12:00:00 AM +00:00
Наконец, мы хотим найти все имена отелей, которые соответствуют слову "hotel":
parameters = new SearchParameters()
{
SearchFields = new[] { "HotelName" }
};
results = indexClient.Documents.Search<Hotel>("hotel", parameters);
WriteDocuments(results);
Ниже приведены результаты, которые включают все поля, так как мы не указали Select свойство:
HotelId: 3
Name: Triple Landscape Hotel
...
Этот шаг завершает учебник, но не останавливайтесь на этом, продолжайте дальше. **Дальнейшие действия предоставляют дополнительные ресурсы для получения дополнительных сведений о Когнитивном поиске Azure.
Дальнейшие шаги
- Ознакомьтесь со ссылками на пакет SDK для .NET и REST API.
- Просмотрите соглашения об именовании , чтобы узнать правила именования различных объектов.
- Просмотрите поддерживаемые типы данных в Когнитивном поиске Azure.