Partilhar via


Tutorial: Índice de várias fontes de dados usando o SDK do .NET

O Azure AI Search dá suporte à importação, análise e indexação de dados de várias fontes de dados em um único índice de pesquisa consolidado.

Este tutorial em C# usa a biblioteca de cliente Azure.Search.Documents no SDK do Azure para .NET para indexar dados de hotel de exemplo de uma instância do Azure Cosmos DB. Em seguida, você mescla os dados com os detalhes do quarto de hotel extraídos de documentos do Armazenamento de Blob do Azure. O resultado é um índice de pesquisa de hotéis combinado contendo documentos de hotéis, com quartos como tipos de dados complexos.

Neste tutorial, você:

  • Carregar dados de amostra para fontes de dados
  • Identificar a chave do documento
  • Definir e criar o índice
  • Indexar dados de hotel do Azure Cosmos DB
  • Fusão de dados de quartos de hotel a partir do Blob Storage

Descrição geral

Este tutorial usa Azure.Search.Documents para criar e executar vários indexadores. Carregas dados de amostra para duas fontes Azure e configuras um indexador que extrai de ambas as fontes para preencher um único índice de pesquisa. Os dois conjuntos de dados devem ter um valor em comum para dar suporte à mesclagem. Neste tutorial, esse campo é um ID. Desde que exista um campo comum para suportar o mapeamento, um indexador pode fundir dados de recursos díspares: dados estruturados do Azure SQL, dados não estruturados do Blob Storage, ou qualquer combinação de fontes de dados suportadas no Azure.

Uma versão concluída do código neste tutorial pode ser encontrada no seguinte projeto:

Pré-requisitos

Nota

Você pode usar um serviço de pesquisa gratuito para este tutorial. A camada gratuita limita você a três índices, três indexadores e três fontes de dados. Este tutorial cria um de cada. Antes de começar, certifique-se de que tem espaço no seu serviço para aceitar os novos recursos.

Preparar os serviços

Este tutorial usa o Azure AI Search para indexação e consultas, o Azure Cosmos DB para o primeiro conjunto de dados e o Armazenamento de Blob do Azure para o segundo conjunto de dados.

Se possível, crie todos os serviços na mesma região e grupo de recursos para proximidade e capacidade de gerenciamento. Na prática, seus serviços podem estar em qualquer região.

Este exemplo usa dois pequenos conjuntos de dados que descrevem sete hotéis fictícios. Um conjunto descreve os próprios hotéis e será carregado em um banco de dados do Azure Cosmos DB. O outro conjunto contém detalhes do quarto de hotel e é fornecido como sete arquivos JSON separados a serem carregados no Armazenamento de Blobs do Azure.

Comece com o Azure Cosmos DB

  1. Inicie sessão no portal Azure e selecione a sua conta Azure Cosmos DB.

  2. No painel esquerdo, selecione Explorador de Dados.

  3. Selecione novo contentor>nova base de dados.

    Criar uma nova base de dados

  4. Insira hotel-rooms-db para o nome. Aceite os valores padrão para as configurações restantes.

    Configurar banco de dados

  5. Crie um contentor que tenha como alvo a base de dados que criou anteriormente. Introduza hotéis para o nome do contentor e /HotelId para a chave da partição.

    Adicionar contentor

  6. Seleciona Itens> e depois seleciona Carregar Item na barra de comandos.

  7. Carrega o ficheiro JSON da cosmosdb pasta em multiple-data-sources/v11.

    Carregar para a coleção do Azure Cosmos DB

  8. Use o botão de atualizar para atualizar a sua visão dos itens na coleção do hotel. Você verá sete novos documentos de banco de dados listados.

  9. No painel esquerdo, selecione Teclas de configurações>.

  10. Anota um string de conexão. Você precisa desse valor para appsettings.json em uma etapa posterior. Se não usou o nome sugerido para a base de dados de quartos de hotel , copie também o nome da base de dados.

Armazenamento de Blobs do Azure

  1. Entre no portal do Azure e selecione sua conta de Armazenamento do Azure.

  2. No painel esquerdo, selecione Contêineres de armazenamento de> dados.

  3. Crie um contêiner de blob chamado hotel-rooms para armazenar os arquivos JSON de quarto de hotel de exemplo. Podes definir o nível de acesso para qualquer valor válido.

    Criar um contentor de blobs

  4. Abre o contentor e depois seleciona Carregar na barra de comandos.

  5. Carrega os sete ficheiros JSON da blob pasta em multiple-data-sources/v11.

    Carregar ficheiros

  6. No painel esquerdo, selecione Segurança + chaves de acesso à rede>.

  7. Regista o nome da conta e uma cadeia de ligação. Você precisa de ambos os valores para appsettings.json em uma etapa posterior.

O terceiro componente é o Azure AI Search, que você pode criar no portal do Azure ou encontrar um serviço de pesquisa existente em seus recursos do Azure.

Para autenticar no seu serviço de pesquisa, precisa do URL do serviço e de uma chave de acesso. Ter uma chave válida estabelece confiança por pedido entre a aplicação que envia o pedido e o serviço que o está a tratar.

  1. Entre no portal do Azure e selecione seu serviço de pesquisa.

  2. No painel esquerdo, selecione Visão geral.

  3. Tome nota do URL, que deve ter a aparência de https://my-service.search.windows.net.

  4. No painel esquerdo, selecione Teclas de configurações>.

  5. Registe uma chave de administrador para obter direitos completos sobre o serviço. Existem duas chaves de administrador intercambiáveis, fornecidas para continuidade operacional caso seja necessário substituir uma. Pode usar qualquer uma das teclas nas solicitações para adicionar, modificar e eliminar objetos.

Configurar o ambiente

  1. Abra o AzureSearchMultipleDataSources.sln ficheiro do multiple-data-sources/v11 no Visual Studio.

  2. No Explorador de Soluções, clique com o botão direito no projeto e selecione Gerir Pacotes NuGet para Solução....

  3. No separador Navegar , encontre e instale os seguintes pacotes:

    • Azure.Search.Documents (versão 11.0 ou posterior)

    • Microsoft.Extensions.Configuration

    • Microsoft.Extensões.Configuração.Json

  4. No Explorador de Soluções, edite o appsettings.json ficheiro com a informação de ligação que recolheu nos passos anteriores.

    {
      "SearchServiceUri": "<YourSearchServiceURL>",
      "SearchServiceAdminApiKey": "<YourSearchServiceAdminApiKey>",
      "BlobStorageAccountName": "<YourBlobStorageAccountName>",
      "BlobStorageConnectionString": "<YourBlobStorageConnectionString>",
      "CosmosDBConnectionString": "<YourCosmosDBConnectionString>",
      "CosmosDBDatabaseName": "hotel-rooms-db"
    }
    

Mapear campos-chave

A mesclagem de conteúdo requer que ambos os fluxos de dados estejam direcionando os mesmos documentos no índice de pesquisa.

No Azure AI Search, o campo chave identifica exclusivamente cada documento. Cada índice de pesquisa deve ter exatamente um campo chave do tipo Edm.String. Esse campo-chave deve estar presente para cada documento em uma fonte de dados adicionada ao índice. (Na verdade, é o único campo obrigatório.)

Ao indexar dados de várias fontes de dados, verifique se cada linha ou documento de entrada contém uma chave de documento comum. Isso permite mesclar dados de dois documentos de origem fisicamente distintos em um novo documento de pesquisa no índice combinado.

Muitas vezes, requer algum planejamento inicial para identificar uma chave de documento significativa para seu índice e garantir que ela exista em ambas as fontes de dados. Nesta demonstração, a HotelId chave de cada hotel no Azure Cosmos DB também está presente nos blobs JSON das salas no Blob Storage.

Os indexadores do Azure AI Search podem usar mapeamentos de campo para renomear e até mesmo reformatar campos de dados durante o processo de indexação, para que os dados de origem possam ser direcionados para o campo de índice correto. Por exemplo, no Azure Cosmos DB, o identificador de hotel é chamado HotelId, mas nos arquivos de blob JSON para os quartos de hotel, o identificador de hotel é nomeado Id. O programa lida com essa discrepância mapeando o Id campo dos blobs para o HotelId campo chave no indexador.

Nota

Na maioria dos casos, as chaves de documento geradas automaticamente, como as criadas por padrão por alguns indexadores, não são boas chaves de documento para índices combinados. Em geral, use um valor de chave significativo e exclusivo que já existe em suas fontes de dados ou pode ser facilmente adicionado.

Explore o código

Quando os dados e as definições de configuração estiverem implementados, o programa AzureSearchMultipleDataSources.sln de exemplo deve estar pronto para compilar e executar.

Este aplicativo de console C#/.NET simples executa as seguintes tarefas:

  • Cria um novo índice com base na estrutura de dados da classe C# Hotel, que também faz referência às classes Address e Room.
  • Cria uma nova fonte de dados e um indexador que mapeia dados do Azure Cosmos DB para campos de índice. Estes são ambos os objetos no Azure AI Search.
  • Executa o indexador para carregar dados de hotel do Azure Cosmos DB.
  • Cria uma segunda fonte de dados e um indexador que mapeia dados de blob JSON para campos de índice.
  • Executa o segundo indexador para carregar os dados dos quartos de hotel a partir do Blob Storage.

Antes de executares o programa, dedica um minuto a estudar o código, a definição do índice e a definição do indexador. O código relevante está em dois ficheiros:

  • Hotel.cs contém o esquema que define o índice.
  • Program.cs contém funções que criam o índice Azure AI Search, fontes de dados e indexadores, e carregam os resultados combinados no índice.

Criar um índice

Este programa de exemplo usa CreateIndexAsync para definir e criar um índice do Azure AI Search. Ele aproveita a classe FieldBuilder para gerar uma estrutura de índice a partir de uma classe de modelo de dados C#.

O modelo de dados é definido pela classe Hotel, que também contém referências às classes Address e Room. O FieldBuilder detalha várias definições de classe para gerar uma estrutura de dados complexa para o índice. As tags de metadados são usadas para definir os atributos de cada campo, como se é pesquisável ou classificável.

O programa exclui qualquer índice existente com o mesmo nome antes de criar o novo, caso você queira executar este exemplo mais de uma vez.

Os seguintes excertos do Hotel.cs ficheiro mostram campos únicos, seguidos de uma referência a outra classe de modelo de dados, Room[], que por sua vez está definida no Room.cs ficheiro (não mostrada).

. . .
[SimpleField(IsFilterable = true, IsKey = true)]
public string HotelId { get; set; }

[SearchableField(IsFilterable = true, IsSortable = true)]
public string HotelName { get; set; }
. . .
public Room[] Rooms { get; set; }
. . .

No Program.cs ficheiro, é definido um SearchIndex com um nome e uma coleção de campos gerados pelo FieldBuilder.Build método, e depois criado da seguinte forma:

private static async Task CreateIndexAsync(string indexName, SearchIndexClient indexClient)
{
    // Create a new search index structure that matches the properties of the Hotel class.
    // The Address and Room classes are referenced from the Hotel class. The FieldBuilder
    // will enumerate these to create a complex data structure for the index.
    FieldBuilder builder = new FieldBuilder();
    var definition = new SearchIndex(indexName, builder.Build(typeof(Hotel)));

    await indexClient.CreateIndexAsync(definition);
}

Criar fonte de dados e indexador do Azure Cosmos DB

O programa principal inclui lógica para criar a fonte de dados do Azure Cosmos DB para os dados de hotéis.

Primeiro, ele concatena o nome do banco de dados do Azure Cosmos DB com a cadeia de conexão. Em seguida, define um objeto SearchIndexerDataSourceConnection .

private static async Task CreateAndRunCosmosDbIndexerAsync(string indexName, SearchIndexerClient indexerClient)
{
    // Append the database name to the connection string
    string cosmosConnectString =
        configuration["CosmosDBConnectionString"]
        + ";Database="
        + configuration["CosmosDBDatabaseName"];

    SearchIndexerDataSourceConnection cosmosDbDataSource = new SearchIndexerDataSourceConnection(
        name: configuration["CosmosDBDatabaseName"],
        type: SearchIndexerDataSourceType.CosmosDb,
        connectionString: cosmosConnectString,
        container: new SearchIndexerDataContainer("hotels"));

    // The Azure Cosmos DB data source does not need to be deleted if it already exists,
    // but the connection string might need to be updated if it has changed.
    await indexerClient.CreateOrUpdateDataSourceConnectionAsync(cosmosDbDataSource);

Depois de criada a fonte de dados, o programa configura um indexador Azure Cosmos DB chamado hotel-rooms-cosmos-indexer.

O programa atualiza todos os indexadores existentes com o mesmo nome, substituindo o indexador existente pelo conteúdo do código anterior. Ele também inclui ações de redefinição e execução, caso você queira executar este exemplo mais de uma vez.

O exemplo a seguir define uma agenda para o indexador, para que ele seja executado uma vez por dia. Você pode remover a propriedade schedule dessa chamada se não quiser que o indexador seja executado automaticamente novamente no futuro.

SearchIndexer cosmosDbIndexer = new SearchIndexer(
    name: "hotel-rooms-cosmos-indexer",
    dataSourceName: cosmosDbDataSource.Name,
    targetIndexName: indexName)
{
    Schedule = new IndexingSchedule(TimeSpan.FromDays(1))
};

// Indexers keep metadata about how much they have already indexed.
// If we already ran the indexer, it "remembers" and does not run again.
// To avoid this, reset the indexer if it exists.
try
{
    await indexerClient.GetIndexerAsync(cosmosDbIndexer.Name);
    // Reset the indexer if it exists.
    await indexerClient.ResetIndexerAsync(cosmosDbIndexer.Name);
}
catch (RequestFailedException ex) when (ex.Status == 404)
{
    // If the indexer does not exist, 404 will be thrown.
}

await indexerClient.CreateOrUpdateIndexerAsync(cosmosDbIndexer);

Console.WriteLine("Running Azure Cosmos DB indexer...\n");

try
{
    // Run the indexer.
    await indexerClient.RunIndexerAsync(cosmosDbIndexer.Name);
}
catch (RequestFailedException ex) when (ex.Status == 429)
{
    Console.WriteLine("Failed to run indexer: {0}", ex.Message);
}

Este exemplo inclui um bloco try-catch simples para relatar quaisquer erros que possam ocorrer durante a execução.

Depois que o indexador do Azure Cosmos DB é executado, o índice de pesquisa contém um conjunto completo de documentos de hotel de exemplo. No entanto, o campo de quartos para cada hotel é um array vazio, uma vez que a fonte de dados do Azure Cosmos DB omite detalhes dos quartos. De seguida, o programa extrai do Blob Storage para carregar e integrar os dados do ambiente.

Criar fonte de dados do Blob Storage e indexador

Para obter os detalhes da sala, o programa configura primeiro uma fonte de dados Blob Storage para referenciar um conjunto de ficheiros blob JSON individuais.

private static async Task CreateAndRunBlobIndexerAsync(string indexName, SearchIndexerClient indexerClient)
{
    SearchIndexerDataSourceConnection blobDataSource = new SearchIndexerDataSourceConnection(
        name: configuration["BlobStorageAccountName"],
        type: SearchIndexerDataSourceType.AzureBlob,
        connectionString: configuration["BlobStorageConnectionString"],
        container: new SearchIndexerDataContainer("hotel-rooms"));

    // The blob data source does not need to be deleted if it already exists,
    // but the connection string might need to be updated if it has changed.
    await indexerClient.CreateOrUpdateDataSourceConnectionAsync(blobDataSource);

Após a criação da fonte de dados, o programa configura um indexador blob chamado hotel-rooms-blob-indexer, como mostrado abaixo.

Os blobs JSON contêm um campo chave chamado Id em vez de HotelId. O código usa a classe FieldMapping para instruir o indexador a direcionar o valor do campo Id para a chave do documento HotelId no índice.

Os indexadores de Blob Storage podem usar IndexingParameters para especificar um modo de análise sintática. Você deve definir diferentes modos de análise dependendo se os blobs representam um único documento ou vários documentos dentro do mesmo blob. Neste exemplo, cada blob representa um único documento JSON, portanto, o código usa o json modo de análise. Para obter mais informações sobre parâmetros de análise de indexador para blobs JSON, consulte Blobs JSON de índice.

Este exemplo define uma agenda para o indexador, para que ele seja executado uma vez por dia. Você pode remover a propriedade schedule dessa chamada se não quiser que o indexador seja executado automaticamente novamente no futuro.

IndexingParameters parameters = new IndexingParameters();
parameters.Configuration.Add("parsingMode", "json");

SearchIndexer blobIndexer = new SearchIndexer(
    name: "hotel-rooms-blob-indexer",
    dataSourceName: blobDataSource.Name,
    targetIndexName: indexName)
{
    Parameters = parameters,
    Schedule = new IndexingSchedule(TimeSpan.FromDays(1))
};

// Map the Id field in the Room documents to the HotelId key field in the index
blobIndexer.FieldMappings.Add(new FieldMapping("Id") { TargetFieldName = "HotelId" });

// Reset the indexer if it already exists
try
{
    await indexerClient.GetIndexerAsync(blobIndexer.Name);
    await indexerClient.ResetIndexerAsync(blobIndexer.Name);
}
catch (RequestFailedException ex) when (ex.Status == 404) { }

await indexerClient.CreateOrUpdateIndexerAsync(blobIndexer);

try
{
    // Run the indexer.
    await searchService.Indexers.RunAsync(blobIndexer.Name);
}
catch (CloudException e) when (e.Response.StatusCode == (HttpStatusCode)429)
{
    Console.WriteLine("Failed to run indexer: {0}", e.Response.Content);
}

Como o índice já está preenchido com dados de hotel do banco de dados do Azure Cosmos DB, o indexador de blob atualiza os documentos existentes no índice e adiciona os detalhes da sala.

Nota

Se você tiver os mesmos campos não-chave em ambas as fontes de dados e os dados nesses campos não corresponderem, o índice conterá os valores do indexador executado mais recentemente. No nosso exemplo, ambas as fontes de dados contêm um HotelName campo. Se por alguma razão os dados neste campo forem diferentes, para documentos com o mesmo valor-chave, os HotelName dados da fonte de dados indexada mais recentemente são o valor armazenado no índice.

Depois de executar o programa, pode explorar o índice de pesquisa preenchido usando o explorador de pesquisa no portal Azure.

  1. Entre no portal do Azure e selecione seu serviço de pesquisa.

  2. No painel esquerdo, selecione Gerenciamento de pesquisa>Índices.

  3. Selecione a amostra de quartos de hotel da lista de índices.

  4. No separador do explorador de pesquisa , introduza uma consulta para um termo como Luxury.

    Deves ver pelo menos um documento nos resultados. Este documento deve conter uma lista de objetos de sala na sua matriz Rooms.

Repor e executar novamente

Nos estágios experimentais iniciais de desenvolvimento, a abordagem mais prática para iteração de design é excluir os objetos da Pesquisa de IA do Azure e permitir que seu código os reconstrua. Os nomes dos recursos são exclusivos. Quando elimina um objeto, pode recriá-lo com o mesmo nome.

O código de exemplo verifica se há objetos existentes e os exclui ou atualiza para que você possa executar novamente o programa. Você também pode usar o portal do Azure para excluir índices, indexadores e fontes de dados.

Clean up resources (Limpar recursos)

Quando estiver a trabalhar na sua própria subscrição, no final de um projeto, é uma boa ideia remover os recursos de que já não necessita. Os recursos que deixar em execução podem custar dinheiro. Pode eliminar recursos individualmente ou eliminar o grupo de recursos para eliminar todo o conjunto de recursos.

Você pode localizar e gerenciar recursos no portal do Azure usando o link Todos os recursos ou Grupos de recursos no painel esquerdo.

Próximo passo

Agora que você está familiarizado com a ingestão de dados de várias fontes, dê uma olhada mais de perto na configuração do indexador, começando com o Azure Cosmos DB: