Como usar Azure.Search.Documents em um aplicativo .NET
Este artigo explica como criar e gerenciar objetos de pesquisa usando C# e a biblioteca de cliente Azure.Search.Documents (versão 11) no SDK do Azure para .NET.
Sobre a versão 11
O SDK do Azure para .NET inclui uma biblioteca de cliente Azure.Search.Documents da equipe do SDK do Azure que é funcionalmente equivalente à biblioteca de cliente anterior, Microsoft.Azure.Search. A versão 11 é mais consistente em termos de programação do Azure. Alguns exemplos incluem AzureKeyCredential
autenticação de chave e System.Text.Json.Serialization para serialização JSON.
Tal como nas versões anteriores, pode utilizar esta biblioteca para:
- Crie e gerencie índices de pesquisa, fontes de dados, indexadores, conjuntos de habilidades e mapas de sinônimos
- Carregar e gerenciar documentos de pesquisa em um índice
- Execute consultas, tudo sem ter que lidar com os detalhes de HTTP e JSON
- Invoque e gerencie o enriquecimento de IA (conjuntos de habilidades) e saídas
A biblioteca é distribuída como um único pacote NuGet que inclui todas as APIs usadas para acesso programático a um serviço de pesquisa.
A biblioteca de cliente define classes como SearchIndex
, SearchField
e SearchDocument
, bem como operações como SearchIndexClient.CreateIndex
e SearchClient.Search
sobre as SearchIndexClient
classes and SearchClient
. Essas classes são organizadas nos seguintes namespaces:
Azure.Search.Documents
Azure.Search.Documents.Indexes
Azure.Search.Documents.Indexes.Models
Azure.Search.Documents.Models
A versão 11 visa a especificação do serviço de pesquisa 2020-06-30.
A biblioteca de cliente não fornece operações de gerenciamento de serviços, como criar e dimensionar serviços de pesquisa e gerenciar chaves de API. Se você precisar gerenciar seus recursos de pesquisa de um aplicativo .NET, use a biblioteca Microsoft.Azure.Management.Search no SDK do Azure para .NET.
Atualizar para v11
Se você estiver usando a versão anterior do SDK do .NET e quiser atualizar para a versão atual disponível em geral, consulte Atualizar para o SDK do .NET do Azure AI Search versão 11.
Requisitos do SDK
Visual Studio 2019 ou posterior.
Seu próprio serviço Azure AI Search. Para usar o SDK, você precisa do nome do seu serviço e de uma ou mais chaves de API. Crie um serviço no portal do Azure se não tiver um.
Baixe o pacote NuGet usando Ferramentas>Gerenciador de Pacotes>NuGet Gerencie pacotes NuGet para solução no Visual Studio. Procure o nome
Azure.Search.Documents
do pacote .
O SDK do Azure para .NET está em conformidade com o .NET Standard 2.0.
Aplicação de exemplo
Este artigo ensina por exemplo, baseando-se no exemplo de código DotNetHowTo no GitHub para ilustrar conceitos fundamentais no Azure AI Search e como criar, carregar e consultar um índice de pesquisa.
Para o resto deste artigo, suponha um novo índice chamado hotéis, preenchido com alguns documentos, com várias consultas que correspondem aos resultados.
O exemplo a seguir mostra o programa principal, com o fluxo geral:
// 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();
SearchIndexClient indexClient = CreateSearchIndexClient(configuration);
string indexName = configuration["SearchIndexName"];
Console.WriteLine("{0}", "Deleting index...\n");
DeleteIndexIfExists(indexName, indexClient);
Console.WriteLine("{0}", "Creating index...\n");
CreateIndex(indexName, indexClient);
SearchClient searchClient = indexClient.GetSearchClient(indexName);
Console.WriteLine("{0}", "Uploading documents...\n");
UploadDocuments(searchClient);
SearchClient indexClientForQueries = CreateSearchClientForQueries(indexName, configuration);
Console.WriteLine("{0}", "Run queries...\n");
RunQueries(indexClientForQueries);
Console.WriteLine("{0}", "Complete. Press any key to end application...\n");
Console.ReadKey();
}
Em seguida, é uma captura de tela parcial da saída, supondo que você execute este aplicativo com um nome de serviço válido e chaves de API:
Tipos de clientes
A biblioteca de cliente usa três tipos de cliente para várias operações: SearchIndexClient
para criar, atualizar ou excluir índices, SearchClient
para carregar ou consultar um índice e SearchIndexerClient
para trabalhar com indexadores e conjuntos de habilidades. Este artigo concentra-se nos dois primeiros.
No mínimo, todos os clientes exigem o nome do serviço ou ponto de extremidade e uma chave de API. É comum fornecer essas informações em um arquivo de configuração, semelhante ao que você encontra no arquivo appsettings.json do aplicativo de exemplo DotNetHowTo. Para ler a partir do arquivo de configuração, adicione using Microsoft.Extensions.Configuration;
ao seu programa.
A instrução a seguir cria o cliente de índice usado para criar, atualizar ou excluir índices. É necessário um ponto de extremidade de serviço e uma chave de API de administração.
private static SearchIndexClient CreateSearchIndexClient(IConfigurationRoot configuration)
{
string searchServiceEndPoint = configuration["YourSearchServiceEndPoint"];
string adminApiKey = configuration["YourSearchServiceAdminApiKey"];
SearchIndexClient indexClient = new SearchIndexClient(new Uri(searchServiceEndPoint), new AzureKeyCredential(adminApiKey));
return indexClient;
}
A próxima instrução cria o cliente de pesquisa usado para carregar documentos ou executar consultas. SearchClient
requer um índice. Você precisa de uma chave de API de administração para carregar documentos, mas pode usar uma chave de API de consulta para executar consultas.
string indexName = configuration["SearchIndexName"];
private static SearchClient CreateSearchClientForQueries(string indexName, IConfigurationRoot configuration)
{
string searchServiceEndPoint = configuration["YourSearchServiceEndPoint"];
string queryApiKey = configuration["YourSearchServiceQueryApiKey"];
SearchClient searchClient = new SearchClient(new Uri(searchServiceEndPoint), indexName, new AzureKeyCredential(queryApiKey));
return searchClient;
}
Nota
Se você fornecer uma chave inválida para a operação de importação (por exemplo, uma chave de consulta onde uma chave de administrador foi necessária), o SearchClient
lançará um CloudException
com a mensagem de erro Proibido na primeira vez que você chamar um método de operação nele. Se isso acontecer com você, verifique novamente a chave da API.
Excluir o índice
Nos estágios iniciais de desenvolvimento, convém incluir uma DeleteIndex
instrução para excluir um índice de trabalho em andamento para que possa recriá-lo com uma definição atualizada. O código de exemplo para o Azure AI Search geralmente inclui uma etapa de exclusão para que você possa executar novamente o exemplo.
A seguinte linha chama DeleteIndexIfExists
:
Console.WriteLine("{0}", "Deleting index...\n");
DeleteIndexIfExists(indexName, indexClient);
Este método usa o dado SearchIndexClient
para verificar se o índice existe e, em caso afirmativo, o exclui:
private static void DeleteIndexIfExists(string indexName, SearchIndexClient indexClient)
{
try
{
if (indexClient.GetIndex(indexName) != null)
{
indexClient.DeleteIndex(indexName);
}
}
catch (RequestFailedException e) when (e.Status == 404)
{
// Throw an exception if the index name isn't found
Console.WriteLine("The index doesn't exist. No deletion occurred.");
Nota
O código de exemplo neste artigo usa os métodos síncronos para simplificar, mas você deve usar os métodos assíncronos em seus próprios aplicativos para mantê-los escaláveis e responsivos. Por exemplo, no método anterior, você poderia usar DeleteIndexAsync
em vez de DeleteIndex
.
Criar um índice
Você pode usar SearchIndexClient
para criar um índice.
O método a seguir cria um novo SearchIndex
objeto com uma lista de SearchField
objetos que definem o esquema do novo índice. Cada campo tem um nome, tipo de dados e vários atributos que definem seu comportamento de pesquisa.
Os campos podem ser definidos a partir de uma classe de modelo usando FieldBuilder
. A FieldBuilder
classe usa reflexão para criar uma lista de SearchField
objetos para o índice, examinando as propriedades públicas e atributos da classe de modelo dada Hotel
. Veremos mais de perto a Hotel
aula mais adiante.
private static void CreateIndex(string indexName, SearchIndexClient indexClient)
{
FieldBuilder fieldBuilder = new FieldBuilder();
var searchFields = fieldBuilder.Build(typeof(Hotel));
var definition = new SearchIndex(indexName, searchFields);
indexClient.CreateOrUpdateIndex(definition);
}
Além dos campos, você também pode adicionar perfis de pontuação, sugestões ou opções CORS ao índice (esses parâmetros são omitidos da amostra por brevidade). Você pode encontrar mais informações sobre o SearchIndex
objeto e suas partes constituintes na lista de propriedades SearchIndex, bem como na referência da API REST.
Nota
Você sempre pode criar a lista de Field
objetos diretamente em vez de usar FieldBuilder
, se necessário. Por exemplo, talvez você não queira usar uma classe de modelo ou talvez precise usar uma classe de modelo existente que não deseja modificar adicionando atributos.
Chamar CreateIndex em Main()
Main
Cria um novo índice de hotéis chamando o método anterior:
Console.WriteLine("{0}", "Creating index...\n");
CreateIndex(indexName, indexClient);
Usar uma classe de modelo para representação de dados
O exemplo DotNetHowTo usa classes de modelo para as estruturas de dados Hotel, Address e Room. Hotel
referências Address
, um tipo complexo de nível único (um campo com várias partes) e Room
(uma coleção de campos com várias partes).
Você pode usar esses tipos para criar e carregar o índice e para estruturar a resposta de uma consulta:
// Use-case: <Hotel> in a field definition
FieldBuilder fieldBuilder = new FieldBuilder();
var searchFields = fieldBuilder.Build(typeof(Hotel));
// Use-case: <Hotel> in a response
private static void WriteDocuments(SearchResults<Hotel> searchResults)
{
foreach (SearchResult<Hotel> result in searchResults.GetResults())
{
Console.WriteLine(result.Document);
}
Console.WriteLine();
}
Uma abordagem alternativa é adicionar campos a um índice diretamente. O exemplo a seguir mostra apenas alguns campos.
SearchIndex index = new SearchIndex(indexName)
{
Fields =
{
new SimpleField("hotelId", SearchFieldDataType.String) { IsKey = true, IsFilterable = true, IsSortable = true },
new SearchableField("hotelName") { IsFilterable = true, IsSortable = true },
new SearchableField("hotelCategory") { IsFilterable = true, IsSortable = true },
new SimpleField("baseRate", SearchFieldDataType.Int32) { IsFilterable = true, IsSortable = true },
new SimpleField("lastRenovationDate", SearchFieldDataType.DateTimeOffset) { IsFilterable = true, IsSortable = true }
}
};
Definições de campo
Seu modelo de dados no .NET e seu esquema de índice correspondente devem oferecer suporte à experiência de pesquisa que você gostaria de oferecer ao usuário final. Cada objeto de nível superior no .NET, como um documento de pesquisa em um índice de pesquisa, corresponde a um resultado de pesquisa que você apresentaria na interface do usuário. Por exemplo, em um aplicativo de pesquisa de hotel, seus usuários finais podem querer pesquisar por nome de hotel, características do hotel ou características de um quarto específico.
Dentro de cada classe, um campo é definido com um tipo de dados e atributos que determinam como ele é usado. O nome de cada propriedade pública em cada classe é mapeado para um campo com o mesmo nome na definição de índice.
Dê uma olhada no trecho a seguir que extrai várias definições de campo da classe Hotel. Observe que Address
e Rooms
são tipos C# com suas próprias definições de classe (consulte o código de exemplo se quiser visualizá-los). Ambos são tipos complexos. Para obter mais informações, consulte Como modelar tipos complexos.
public partial class Hotel
{
[SimpleField(IsKey = true, IsFilterable = true)]
public string HotelId { get; set; }
[SearchableField(IsSortable = true)]
public string HotelName { get; set; }
[SearchableField(AnalyzerName = LexicalAnalyzerName.Values.EnLucene)]
public string Description { get; set; }
[SearchableField(IsFilterable = true, IsSortable = true, IsFacetable = true)]
public string Category { get; set; }
[JsonIgnore]
public bool? SmokingAllowed => (Rooms != null) ? Array.Exists(Rooms, element => element.SmokingAllowed == true) : (bool?)null;
[SearchableField]
public Address Address { get; set; }
public Room[] Rooms { get; set; }
Escolha uma classe de campo
Ao definir campos, você pode usar a classe base SearchField
ou modelos auxiliares derivados que servem como modelos, com propriedades pré-configuradas.
Exatamente um campo no índice deve servir como a chave do documento (IsKey = true
). Deve ser uma cadeia de caracteres e deve identificar exclusivamente cada documento. Também é necessário ter IsHidden = true
, o que significa que não pode ser visível nos resultados de pesquisa.
Tipo de campo | Descrição e utilização |
---|---|
SearchField |
Classe base, com a maioria das propriedades definidas como null, exceto Name a que é necessária e AnalyzerName que assume como padrão Lucene. |
SimpleField |
Modelo auxiliar. Pode ser qualquer tipo de dados, é sempre não pesquisável (é ignorado para consultas de pesquisa de texto completo) e é recuperável (não está oculto). Outros atributos estão desativados por padrão, mas podem ser habilitados. Você pode usar um SimpleField para IDs de documento ou campos usados apenas em filtros, facetas ou perfis de pontuação. Em caso afirmativo, certifique-se de aplicar todos os atributos necessários para o cenário, como IsKey = true para uma ID de documento. Para obter mais informações, consulte SimpleFieldAttribute.cs no código-fonte. |
SearchableField |
Modelo auxiliar. Deve ser uma cadeia de caracteres e é sempre pesquisável e recuperável. Outros atributos estão desativados por padrão, mas podem ser habilitados. Como esse tipo de campo é pesquisável, ele suporta sinônimos e o complemento completo das propriedades do analisador. Para obter mais informações, consulte o SearchableFieldAttribute.cs no código-fonte. |
Se você usa a API básica SearchField
ou um dos modelos auxiliares, você deve habilitar explicitamente os atributos de filtro, faceta e classificação. Por exemplo, IsFilterable, IsSortable e IsFacetable devem ser explicitamente atribuídos, conforme mostrado no exemplo anterior.
Adicionar atributos de campo
Observe como cada campo é decorado com atributos como IsFilterable
, IsSortable
, IsKey
e AnalyzerName
. Esses atributos são mapeados diretamente para os atributos de campo correspondentes em um índice do Azure AI Search. A FieldBuilder
classe usa essas propriedades para construir definições de campo para o índice.
Mapeamento de tipo de campo
Os tipos .NET das propriedades são mapeados para seus tipos de campo equivalentes na definição de índice. Por exemplo, a propriedade da cadeia Category
mapeia para o campo category
, que é do tipo Edm.String
. Existem mapeamentos de tipo semelhantes entre bool?
, Edm.Boolean
, DateTimeOffset?
, e Edm.DateTimeOffset
assim por diante.
Por acaso reparou no SmokingAllowed
imóvel?
[JsonIgnore]
public bool? SmokingAllowed => (Rooms != null) ? Array.Exists(Rooms, element => element.SmokingAllowed == true) : (bool?)null;
O JsonIgnore
atributo nessa propriedade informa para não FieldBuilder
serializá-lo para o índice como um campo. Essa é uma ótima maneira de criar propriedades calculadas do lado do cliente que você pode usar como auxiliares em seu aplicativo. Neste caso, a SmokingAllowed
propriedade reflete se algum Room
na Rooms
coleção permite fumar. Se todos forem falsos, isso indica que todo o hotel não permite fumar.
Carregar um índice
A próxima etapa preenche Main
o índice de hotéis recém-criado. Esta população de índice é feita no seguinte método: (Alguns códigos substituídos por ...
para fins de ilustração. Consulte a solução de exemplo completa para obter o código de população de dados completo.)
private static void UploadDocuments(SearchClient searchClient)
{
IndexDocumentsBatch<Hotel> batch = IndexDocumentsBatch.Create(
IndexDocumentsAction.Upload(
new Hotel()
{
HotelId = "1",
HotelName = "Stay-Kay City Hotel",
...
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)",
...
}
}
}),
IndexDocumentsAction.Upload(
new Hotel()
{
HotelId = "2",
HotelName = "Old Century Hotel",
...
{
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)",
...
}
}
}),
IndexDocumentsAction.Upload(
new Hotel()
{
HotelId = "3",
HotelName = "Gastronomic 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)",
...
}
}
}
};
try
{
IndexDocumentsResult result = searchClient.IndexDocuments(batch);
}
catch (Exception)
{
// 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}");
}
Console.WriteLine("Waiting for documents to be indexed...\n");
Thread.Sleep(2000);
Este método tem quatro partes. O primeiro cria uma matriz de três Hotel
objetos, cada um com três Room
objetos que servem como nossos dados de entrada para carregar no índice. Esses dados são codificados para simplificar. Em um aplicativo real, os dados provavelmente vêm de uma fonte de dados externa, como um banco de dados SQL.
A segunda parte cria um IndexDocumentsBatch
contendo os documentos. Você especifica a operação que deseja aplicar ao lote no momento em que o cria, neste caso chamando IndexDocumentsAction.Upload
. O lote é então carregado no índice do Azure AI Search pelo IndexDocuments
método.
Nota
Neste exemplo, você está apenas carregando documentos. Se você quiser mesclar alterações em documentos existentes ou excluir documentos, você pode criar lotes chamando IndexDocumentsAction.Merge
, IndexDocumentsAction.MergeOrUpload
ou IndexDocumentsAction.Delete
em vez disso. Você também pode misturar diferentes operações em um único lote chamando IndexBatch.New
, que usa uma coleção de IndexDocumentsAction
objetos, cada um dos quais diz ao Azure AI Search para executar uma operação específica em um documento. Você pode criar cada um IndexDocumentsAction
com sua própria operação chamando o método correspondente, como IndexDocumentsAction.Merge
, IndexAction.Upload
e assim por diante.
A terceira parte desse método é um bloco catch que lida com um caso de erro importante para indexação. Se o seu serviço de pesquisa não conseguir indexar alguns dos documentos do lote, um RequestFailedException
será lançado. Uma exceção pode acontecer se você estiver indexando documentos enquanto o serviço estiver sob carga pesada. Recomendamos vivamente que processe explicitamente este caso no seu código. Pode atrasar e, em seguida, repetir a indexação dos documentos que falharam, pode iniciar sessão e continuar como no exemplo ou pode fazer algo diferente dependendo dos requisitos de consistência de dados da aplicação. Uma alternativa é usar SearchIndexingBufferedSender para processamento em lote inteligente, liberação automática e novas tentativas para ações de indexação com falha. Para obter mais contexto, consulte o exemplo SearchIndexingBufferedSender.
Finalmente, o método atrasa UploadDocuments
por dois segundos. A indexação acontece de forma assíncrona em seu serviço de pesquisa, portanto, o aplicativo de exemplo precisa esperar um curto período de tempo para garantir que os documentos estejam disponíveis para pesquisa. Este género de atrasos são normalmente necessários apenas para demonstrações gratuitas, testes e aplicações de exemplo.
Chamada UploadDocuments em Main()
O trecho de código a seguir configura uma instância de uso do SearchClient
GetSearchClient
método indexClient. O indexClient usa uma chave de API admin em suas solicitações, que é necessária para carregar ou atualizar documentos.
Uma abordagem alternativa é chamar SearchClient
diretamente, passando uma chave de API admin no AzureKeyCredential
.
SearchClient searchClient = indexClient.GetSearchClient(indexName);
Console.WriteLine("{0}", "Uploading documents...\n");
UploadDocuments(searchClient);
Executar consultas
Primeiro, configure um SearchClient
que leia o ponto de extremidade do serviço e a chave da API de consulta do appsettings.json:
private static SearchClient CreateSearchClientForQueries(string indexName, IConfigurationRoot configuration)
{
string searchServiceEndPoint = configuration["YourSearchServiceEndPoint"];
string queryApiKey = configuration["YourSearchServiceQueryApiKey"];
SearchClient searchClient = new SearchClient(new Uri(searchServiceEndPoint), indexName, new AzureKeyCredential(queryApiKey));
return searchClient;
}
Em segundo lugar, defina um método que envie uma solicitação de consulta.
Cada vez que o método executa uma consulta, ele cria um novo SearchOptions
objeto. Este objeto é usado para especificar opções adicionais para a consulta, como classificação, filtragem, paginação e facetagem. Neste método, estamos definindo a Filter
propriedade , Select
e OrderBy
para consultas diferentes. Para obter mais informações sobre a sintaxe da expressão de consulta de pesquisa, sintaxe de consulta simples.
A próxima etapa é a execução da consulta. A execução da pesquisa é feita usando o SearchClient.Search
método. Para cada consulta, passe o texto de pesquisa para usar como uma cadeia de caracteres (ou "*"
se não houver texto de pesquisa), além das opções de pesquisa criadas anteriormente. Também especificamos Hotel
como o parâmetro type para SearchClient.Search
, que diz ao SDK para desserializar documentos nos resultados da pesquisa em objetos do tipo Hotel
.
private static void RunQueries(SearchClient searchClient)
{
SearchOptions options;
SearchResults<Hotel> results;
Console.WriteLine("Query 1: Search for 'motel'. Return only the HotelName in results:\n");
options = new SearchOptions();
options.Select.Add("HotelName");
results = searchClient.Search<Hotel>("motel", options);
WriteDocuments(results);
Console.Write("Query 2: Apply a filter to find hotels with rooms cheaper than $100 per night, ");
Console.WriteLine("returning the HotelId and Description:\n");
options = new SearchOptions()
{
Filter = "Rooms/any(r: r/BaseRate lt 100)"
};
options.Select.Add("HotelId");
options.Select.Add("Description");
results = searchClient.Search<Hotel>("*", options);
WriteDocuments(results);
Console.Write("Query 3: 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");
options =
new SearchOptions()
{
Size = 2
};
options.OrderBy.Add("LastRenovationDate desc");
options.Select.Add("HotelName");
options.Select.Add("LastRenovationDate");
results = searchClient.Search<Hotel>("*", options);
WriteDocuments(results);
Console.WriteLine("Query 4: Search the HotelName field for the term 'hotel':\n");
options = new SearchOptions();
options.SearchFields.Add("HotelName");
//Adding details to select, because "Location" isn't supported yet when deserializing search result to "Hotel"
options.Select.Add("HotelId");
options.Select.Add("HotelName");
options.Select.Add("Description");
options.Select.Add("Category");
options.Select.Add("Tags");
options.Select.Add("ParkingIncluded");
options.Select.Add("LastRenovationDate");
options.Select.Add("Rating");
options.Select.Add("Address");
options.Select.Add("Rooms");
results = searchClient.Search<Hotel>("hotel", options);
WriteDocuments(results);
}
Em terceiro lugar, defina um método que escreva a resposta, imprimindo cada documento no console:
private static void WriteDocuments(SearchResults<Hotel> searchResults)
{
foreach (SearchResult<Hotel> result in searchResults.GetResults())
{
Console.WriteLine(result.Document);
}
Console.WriteLine();
}
Chamar RunQueries em Main()
SearchClient indexClientForQueries = CreateSearchClientForQueries(indexName, configuration);
Console.WriteLine("{0}", "Running queries...\n");
RunQueries(indexClientForQueries);
Explore construções de consulta
Vamos dar uma olhada mais de perto em cada uma das consultas por vez. Aqui está o código para executar a primeira consulta:
options = new SearchOptions();
options.Select.Add("HotelName");
results = searchClient.Search<Hotel>("motel", options);
WriteDocuments(results);
Neste caso, estamos pesquisando todo o índice para a palavra motel em qualquer campo pesquisável e queremos apenas recuperar os nomes dos Select
hotéis, conforme especificado pela opção. Eis os resultados:
Name: Stay-Kay City Hotel
Name: Old Century Hotel
Na segunda consulta, use um filtro para selecionar quartos com uma taxa noturna inferior a US$ 100. Devolva apenas o ID do hotel e a descrição nos resultados:
options = new SearchOptions()
{
Filter = "Rooms/any(r: r/BaseRate lt 100)"
};
options.Select.Add("HotelId");
options.Select.Add("Description");
results = searchClient.Search<Hotel>("*", options);
Esta consulta usa uma expressão OData $filter
, Rooms/any(r: r/BaseRate lt 100)
, para filtrar os documentos no índice. Ele usa qualquer operador para aplicar o 'BaseRate lt 100' a cada item da coleção Rooms. Para obter mais informações, consulte Sintaxe do filtro OData.
Na terceira consulta, encontre os dois principais hotéis que foram renovados mais recentemente e mostre o nome do hotel e a data da última renovação. Aqui está o código:
options =
new SearchOptions()
{
Size = 2
};
options.OrderBy.Add("LastRenovationDate desc");
options.Select.Add("HotelName");
options.Select.Add("LastRenovationDate");
results = searchClient.Search<Hotel>("*", options);
WriteDocuments(results);
Na última consulta, encontre todos os nomes de hotéis que correspondem à palavra hotel:
options.Select.Add("HotelId");
options.Select.Add("HotelName");
options.Select.Add("Description");
options.Select.Add("Category");
options.Select.Add("Tags");
options.Select.Add("ParkingIncluded");
options.Select.Add("LastRenovationDate");
options.Select.Add("Rating");
options.Select.Add("Address");
options.Select.Add("Rooms");
results = searchClient.Search<Hotel>("hotel", options);
WriteDocuments(results);
Esta seção conclui esta introdução ao SDK do .NET, mas não pare por aqui. A próxima seção sugere outros recursos para aprender mais sobre programação com o Azure AI Search.
Conteúdos relacionados
Navegue pela documentação de referência da API para Azure.Search.Documents e API REST
Procure outros exemplos de código baseados em Azure.Search.Documents em azure-search-dotnet-samples e search-dotnet-getting-started
Revise as convenções de nomenclatura para aprender as regras para nomear vários objetos