Dela via


Självstudie: Index från flera datakällor med hjälp av .NET SDK

Azure AI Search kan importera, analysera och indexera data från flera datakällor till ett enda konsoliderat sökindex.

I den här C#-självstudien används klientbiblioteket Azure.Search.Documents i Azure SDK för .NET för att indexering av exempel på hotelldata från en Azure Cosmos DB-instans och sammanfogar det med hotellrumsinformation som hämtats från Azure Blob Storage-dokument. Resultatet är ett kombinerat hotellsökningsindex som innehåller hotelldokument, med rum som komplexa datatyper.

I den här självstudien utför du följande uppgifter:

  • Ladda upp exempeldata och skapa datakällor
  • Identifiera dokumentnyckeln
  • Definiera och skapa indexet
  • Indexering av hotelldata från Azure Cosmos DB
  • Slå samman hotellrumsdata från bloblagring

Om du inte har någon Azure-prenumeration skapar du ett kostnadsfritt konto innan du börjar.

Översikt

I den här självstudien används Azure.Search.Documents för att skapa och köra flera indexerare. I den här självstudien konfigurerar du två Azure-datakällor så att du kan konfigurera en indexerare som hämtar från båda för att fylla i ett enda sökindex. De två datauppsättningarna måste ha ett gemensamt värde för att stödja sammanfogningen. I det här exemplet är fältet ett ID. Så länge det finns ett gemensamt fält som stöder mappningen kan en indexerare slå samman data från olika resurser: strukturerade data från Azure SQL, ostrukturerade data från Blob Storage eller valfri kombination av datakällor som stöds i Azure.

En färdig version av koden i den här självstudien finns i följande projekt:

Förutsättningar

Kommentar

Du kan använda en kostnadsfri söktjänst för den här självstudien. Den kostnadsfria nivån begränsar dig till tre index, tre indexerare och tre datakällor. I den här kursen skapar du en av varje. Innan du börjar bör du se till att du har plats för din tjänst för att acceptera de nya resurserna.

1 – Skapa tjänster

I den här självstudien används Azure AI Search för indexering och frågor, Azure Cosmos DB för en datauppsättning och Azure Blob Storage för den andra datauppsättningen.

Om möjligt skapar du alla tjänster i samma region och resursgrupp för närhet och hanterbarhet. I praktiken kan dina tjänster finnas i valfri region.

Det här exemplet använder två små datamängder som beskriver sju fiktiva hotell. En uppsättning beskriver själva hotellen och läses in i en Azure Cosmos DB-databas. Den andra uppsättningen innehåller information om hotellrum och tillhandahålls som sju separata JSON-filer som ska laddas upp till Azure Blob Storage.

Börja med Azure Cosmos DB

  1. Logga in på Azure Portal och navigera sedan till översiktssidan för ditt Azure Cosmos DB-konto.

  2. Välj Datautforskaren och välj sedan Ny databas.

    Skapa en ny databas

  3. Ange namnet hotel-rooms-db. Acceptera standardvärden för de återstående inställningarna.

    Konfigurera databas

  4. Skapa en ny behållare. Använd den befintliga databas som du nyss skapade. Ange hotell för containernamnet och använd /HotelId för partitionsnyckeln.

    Lägga till containern

  5. Välj Objekt under hotell och välj sedan Ladda upp objekt i kommandofältet. Gå till och välj sedan filen cosmosdb/HotelsDataSubset_CosmosDb.json i projektmappen.

    Ladda upp till Azure Cosmos DB-samling

  6. Använd knappen Uppdatera för att uppdatera vyn över objekten i hotellsamlingen. Du bör se sju nya databasdokument i listan.

  7. Kopiera en anslutningssträng från sidan Nycklar till Anteckningar. Du behöver det här värdet för appsettings.json i ett senare steg. Om du inte använde det föreslagna databasnamnet "hotel-rooms-db" kopierar du även databasnamnet.

Azure Blob Storage

  1. Logga in på Azure Portal, navigera till ditt Azure Storage-konto, välj Blobar och välj sedan + Container.

  2. Skapa en blobcontainer med namnet hotel-rooms för att lagra exempelfilerna för hotellrums-JSON. Du kan ange den offentliga åtkomstnivån till något av dess giltiga värden.

    Skapa en blobcontainer

  3. När containern har skapats öppnar du den och väljer Ladda upp i kommandofältet. Navigera till mappen som innehåller exempelfilerna. Markera alla och välj sedan Ladda upp.

    Ladda upp filer

  4. Kopiera lagringskontots namn och en anslutningssträng från sidan Åtkomstnycklar till Anteckningar. Du behöver båda värdena för appsettings.json i ett senare steg.

Den tredje komponenten är Azure AI Search, som du kan skapa i Azure Portal eller hitta en befintlig söktjänst i dina Azure-resurser.

Om du vill autentisera till söktjänsten behöver du tjänstens URL och en åtkomstnyckel.

  1. Logga in på Azure Portal och hämta URL:en i söktjänstens översiktssida. Här följer ett exempel på hur en slutpunkt kan se ut: https://mydemo.search.windows.net.

  2. I Inställningar>Nycklar hämtar du en administratörsnyckel för fullständiga rättigheter för tjänsten. Det finns två utbytbara administratörsnycklar som tillhandahålls för affärskontinuitet om du behöver rulla över en. Du kan använda antingen den primära eller sekundära nyckeln på begäranden för att lägga till, ändra och ta bort objekt.

En giltig nyckel upprättar förtroende, i varje begäran, mellan programmet som skickar begäran och tjänsten som hanterar den.

2 – Konfigurera din miljö

  1. Starta Visual Studio och på menyn Verktyg väljer du NuGet Package Manager och sedan Hantera NuGet-paket för lösning....

  2. På fliken Bläddra letar du upp och installerar sedan Azure.Search.Documents (version 11.0 eller senare).

  3. Sök efter NuGet-paketen Microsoft.Extensions.Configuration och Microsoft.Extensions.Configuration.Json och installera dem också.

  4. Öppna lösningsfilen /v11/AzureSearchMultipleDataSources.sln.

  5. I Solution Explorer redigerar du filen appsettings.json för att lägga till anslutningsinformation.

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

De första två posterna är URL:en och administratörsnycklarna för en söktjänst. Använd den fullständiga slutpunkten, till exempel: https://mydemo.search.windows.net.

Nästa poster anger kontonamn och anslutningssträng information för Azure Blob Storage- och Azure Cosmos DB-datakällorna.

3 – Mappa nyckelfält

Sammanslagning av innehåll kräver att båda dataströmmarna riktar in sig på samma dokument i sökindexet.

I Azure AI Search identifierar nyckelfältet varje dokument unikt. Varje sökindex måste ha exakt ett nyckelfält av typen Edm.String. Nyckelfältet måste finnas för varje dokument i en datakälla som läggs till i indexet. (Det är faktiskt det enda obligatoriska fältet.)

När du indexerar data från flera datakällor kontrollerar du att varje inkommande rad eller dokument innehåller en gemensam dokumentnyckel för att sammanfoga data från två fysiskt distinkta källdokument till ett nytt sökdokument i det kombinerade indexet.

Det kräver ofta viss planering i förväg för att identifiera en meningsfull dokumentnyckel för ditt index och se till att den finns i båda datakällorna. I den här demonstrationen HotelId finns även nyckeln för varje hotell i Azure Cosmos DB i rummens JSON-blobar i Blob Storage.

Azure AI Search-indexerare kan använda fältmappningar för att byta namn på och till och med formatera om datafält under indexeringsprocessen, så att källdata kan dirigeras till rätt indexfält. I Azure Cosmos DB kallas HotelIdtill exempel hotellidentifieraren . Men i JSON-blobfilerna för hotellrummen heter Idhotellidentifieraren . Programmet hanterar den här avvikelsen Id genom att mappa fältet från blobarna till HotelId nyckelfältet i indexeraren.

Kommentar

I de flesta fall gör inte automatiskt genererade dokumentnycklar, till exempel de som skapats som standard av vissa indexerare, bra dokumentnycklar för kombinerade index. I allmänhet vill du använda ett meningsfullt, unikt nyckelvärde som redan finns i eller enkelt kan läggas till i dina datakällor.

4 – Utforska koden

När data- och konfigurationsinställningarna är på plats bör exempelprogrammet i /v11/AzureSearchMultipleDataSources.sln vara redo att byggas och köras.

Den här enkla C#/.NET-konsolappen utför följande uppgifter:

  • Skapar ett nytt index baserat på datastrukturen för klassen C# Hotel (som även refererar till klasserna Adress och Rum).
  • Skapar en ny datakälla och en indexerare som mappar Azure Cosmos DB-data till indexfält. Det här är båda objekten i Azure AI Search.
  • Kör indexeraren för att läsa in hotelldata från Azure Cosmos DB.
  • Skapar en andra datakälla och en indexerare som mappar JSON-blobdata till indexfält.
  • Kör den andra indexeraren för att läsa in rumsdata från Blob Storage.

Innan du kör programmet tar det en minut att studera koden och index- och indexeringsdefinitionerna för det här exemplet. Den relevanta koden finns i två filer:

  • Hotel.cs innehåller schemat som definierar indexet
  • Program.cs innehåller funktioner som skapar Azure AI Search-index, datakällor och indexerare och läser in de kombinerade resultaten i indexet.

Skapa ett index

Det här exempelprogrammet använder CreateIndexAsync för att definiera och skapa ett Azure AI Search-index. Den använder klassen FieldBuilder för att generera en indexstruktur från en C#-datamodellklass.

Datamodellen definieras av klassen Hotell, som även innehåller referenser till klasserna Adress och Rum. FieldBuilder ökar detaljnivån genom flera klassdefinitioner för att generera en komplex datastruktur för indexet. Metadatataggar används för att definiera attributen för varje fält, till exempel om det är sökbart eller sorterbart.

Programmet tar bort ett befintligt index med samma namn innan du skapar det nya, om du vill köra det här exemplet mer än en gång.

Följande kodfragment från filen Hotel.cs visar enkla fält, följt av en referens till en annan datamodellklass, Room[], som i sin tur definieras i Room.cs fil (visas inte).

. . .
[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; }
. . .

I Program.cs-filen definieras ett SearchIndex med ett namn och en fältsamling som genereras av FieldBuilder.Build metoden och skapas sedan på följande sätt:

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);
}

Skapa Azure Cosmos DB-datakälla och indexerare

Därefter innehåller huvudprogrammet logik för att skapa Azure Cosmos DB-datakällan för hotelldata.

Först sammanfogar den Azure Cosmos DB-databasnamnet till anslutningssträng. Sedan definieras ett SearchIndexerDataSourceConnection-objekt .

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);

När datakällan har skapats konfigurerar programmet en Azure Cosmos DB-indexerare med namnet hotel-rooms-cosmos-indexer.

Programmet uppdaterar alla befintliga indexerare med samma namn och skriver över den befintliga indexeraren med innehållet i koden ovan. Den innehåller även återställnings- och körningsåtgärder, om du vill köra det här exemplet mer än en gång.

I följande exempel definieras ett schema för indexeraren, så att det körs en gång per dag. Du kan ta bort schemaegenskapen från det här anropet om du inte vill att indexeraren ska köras automatiskt igen i framtiden.

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);
}

Det här exemplet innehåller ett enkelt try-catch-block för att rapportera eventuella fel som kan inträffa under körningen.

När Azure Cosmos DB-indexeraren har körts innehåller sökindexet en fullständig uppsättning exempel på hotelldokument. Rumsfältet för varje hotell är dock en tom matris, eftersom Azure Cosmos DB-datakällan utelämnar rumsinformation. Därefter hämtas programmet från Blob Storage för att läsa in och sammanfoga rumsdata.

Skapa Blob Storage-datakälla och indexerare

För att få rumsinformation konfigurerar programmet först en Blob Storage-datakälla för att referera till en uppsättning enskilda JSON-blobfiler.

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);

När datakällan har skapats konfigurerar programmet en blobindexerare med namnet hotel-rooms-blob-indexer, enligt nedan.

JSON-blobarna innehåller ett nyckelfält med namnet Id i stället för HotelId. Koden använder FieldMapping klassen för att instruera indexeraren att dirigera Id fältvärdet till HotelId dokumentnyckeln i indexet.

Blob Storage-indexerare kan använda IndexingParametrar för att ange ett parsningsläge. Du bör ange olika parsningslägen beroende på om blobar representerar ett enda dokument eller flera dokument i samma blob. I det här exemplet representerar varje blob ett enda JSON-dokument, så koden använder json parsningsläget. Mer information om indexerarens parsningsparametrar för JSON-blobar finns i Index JSON-blobar.

Det här exemplet definierar ett schema för indexeraren, så att det körs en gång per dag. Du kan ta bort schemaegenskapen från det här anropet om du inte vill att indexeraren ska köras automatiskt igen i framtiden.

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);
}

Eftersom indexet redan har fyllts i med hotelldata från Azure Cosmos DB-databasen uppdaterar blobindexeraren de befintliga dokumenten i indexet och lägger till rumsinformationen.

Kommentar

Om du har samma icke-nyckelfält i båda dina datakällor och data i dessa fält inte matchar, kommer indexet att innehålla värdena från den indexerare som kördes senast. I vårt exempel innehåller båda datakällorna ett HotelName-fält . Om data i det här fältet av någon anledning skiljer sig åt, för dokument med samma nyckelvärde, blir HotelName-data från datakällan som indexerades senast det värde som lagras i indexet.

Du kan utforska det ifyllda sökindexet när programmet har körts med hjälp av Sökutforskaren i Azure Portal.

I Azure Portal öppnar du söktjänstens översiktssida och hittar indexet hotel-rooms-sample i listan Index.

Lista över Azure AI Search-index

Välj i indexet hotel-rooms-sample i listan. Du ser ett Search Explorer-gränssnitt för indexet. Ange en fråga för en term som "Lyx". Du bör se minst ett dokument i resultatet, och det här dokumentet bör visa en lista över rumsobjekt i rumsmatrisen.

Återställa och köra igen

I de tidiga experimentella utvecklingsfaserna är det mest praktiska sättet att utforma iteration att ta bort objekten från Azure AI Search och låta koden återskapa dem. Resursnamn är unika. Om du tar bort ett objekt kan du återskapa det med samma namn.

Exempelkoden söker efter befintliga objekt och tar bort eller uppdaterar dem så att du kan köra programmet igen.

Du kan också använda Azure Portal för att ta bort index, indexerare och datakällor.

Rensa resurser

När du arbetar i din egen prenumeration i slutet av ett projekt är det en bra idé att ta bort de resurser som du inte längre behöver. Resurser som fortsätter att köras kostar pengar. Du kan ta bort enstaka resurser eller hela resursgruppen om du vill ta bort alla resurser.

Du kan hitta och hantera resurser i Azure Portal med hjälp av länken Alla resurser eller Resursgrupper i det vänstra navigeringsfönstret.

Nästa steg

Nu när du är bekant med konceptet att mata in data från flera källor ska vi ta en närmare titt på indexerarens konfiguration, från och med Azure Cosmos DB.