Zelfstudie: Indexeren uit meerdere gegevensbronnen met behulp van de .NET SDK

Azure AI Search kan gegevens uit meerdere gegevensbronnen importeren, analyseren en indexeren in één geconsolideerde zoekindex.

In deze C#-zelfstudie wordt de Azure.Search.Documents-clientbibliotheek in de Azure SDK voor .NET gebruikt om voorbeeldgegevens van hotels te indexeren uit een Azure Cosmos DB-exemplaar en deze samen te voegen met gegevens van hotelkamers die zijn opgehaald uit Azure Blob Storage-documenten. Het resultaat is een gecombineerde index voor hotelzoekopdrachten met hoteldocumenten, met kamers als complexe gegevenstypen.

In deze zelfstudie voert u de volgende taken uit:

  • Voorbeeldgegevens uploaden en gegevensbronnen maken
  • De documentsleutel identificeren
  • De index definiëren en maken
  • Hotelgegevens uit Azure Cosmos DB indexeren
  • Hotelkamergegevens uit blobopslag samenvoegen

Als u geen Azure-abonnement hebt, maakt u een gratis account voordat u begint.

Overzicht

In deze zelfstudie wordt gebruikgemaakt van Azure.Search.Documents om meerdere indexeerfuncties te maken en uit te voeren. In deze zelfstudie stelt u twee Azure-gegevensbronnen in, zodat u een Indexeerfunctie kunt configureren waarmee uit beide bronnen informatie wordt opgehaald om één zoekindex te vullen. De twee gegevenssets moeten een gemeenschappelijke waarde hebben om de samenvoeging te ondersteunen. In dit voorbeeld is dit veld een id. Zolang er een algemeen veld is ter ondersteuning van de toewijzing, kan een indexeerfunctie gegevens uit verschillende resources samenvoegen: gestructureerde gegevens uit Azure SQL, ongestructureerde gegevens uit Blob Storage of een combinatie van ondersteunde gegevensbronnen in Azure.

Een voltooide versie van de code in deze zelfstudie vindt u in het volgende project:

Vereisten

Notitie

U kunt een gratis zoekservice gebruiken voor deze zelfstudie. De gratis laag beperkt u tot drie indexen, drie indexeerfuncties en drie gegevensbronnen. In deze zelfstudie wordt één exemplaar van elk onderdeel gemaakt. Voordat u aan de slag gaat, zorg ervoor dat uw service voldoende ruimte heeft voor de nieuwe resources.

1- Services maken

In deze zelfstudie wordt Gebruikgemaakt van Azure AI Search voor indexering en query's, Azure Cosmos DB voor één gegevensset en Azure Blob Storage voor de tweede gegevensset.

Maak, indien mogelijk, alle services in dezelfde regio en resourcegroep voor nabijheid en beheerbaarheid. In de praktijk kunnen uw services zich in elke regio bevinden.

In dit voorbeeld worden twee kleine gegevenssets gebruikt, waarin zeven fictieve hotels worden beschreven. In één set worden de hotels zelf beschreven, en wordt in een Azure Cosmos DB-database geladen. De andere set bevat details over de hotelkamers en is beschikbaar als zeven afzonderlijke JSON-bestanden die moeten worden geüpload naar de Azure-blobopslag.

Beginnen met Azure Cosmos DB

  1. Meld u aan bij Azure Portal en ga naar uw Azure Cosmos DB-account. Open vervolgens de pagina Overzicht.

  2. Selecteer Data Explorer en selecteer Nieuwe database.

    Een nieuwe database maken

  3. Voer de naam hotel-rooms-db in. Accepteer de standaardwaarden voor de overige instellingen.

    Database configureren

  4. Maak een nieuwe container. Gebruik de bestaande database die u zojuist hebt gemaakt. Voer hotels in als containernaam en gebruik /HotelId als partitiesleutel.

    Container toevoegen

  5. Selecteer Items onder hotels en selecteer Item uploaden op de opdrachtbalk. Ga naar en selecteer het bestand cosmosdb/HotelsDataSubset_CosmosDb.json in de projectmap.

    Uploaden naar een Azure Cosmos DB-verzameling

  6. Gebruik de knop Vernieuwen om de weergave van de items in de verzameling hotels te vernieuwen. Er worden zeven nieuwe databasedocumenten weergegeven.

  7. Kopieer een verbindingsreeks op de pagina Sleutels in Kladblok. U hebt deze waarde nodig voor appsettings.json in een latere stap. Als u de voorgestelde databasenaam 'hotel-rooms-db' niet hebt gebruikt, kopieert u ook de databasenaam.

Azure Blob-opslag

  1. Meld u aan bij Azure Portal, navigeer naar uw Azure-opslagaccount, selecteer Blobs en selecteer vervolgens + Container.

  2. Maak een blobcontainer met de naam hotel-rooms om de JSON-voorbeeldbestanden voor hotelkamers op te slaan. U kunt het niveau voor openbare toegang instellen op een van de geldige waarden.

    Een blobcontainer maken

  3. Nadat de container is gemaakt, opent u deze en selecteert u Uploaden op de opdrachtbalk. Navigeer naar de map met de voorbeeldbestanden. Selecteer ze allemaal en selecteer vervolgens Uploaden.

    Bestanden uploaden

  4. Kopieer de naam van het opslagaccount en een verbindingsreeks van de pagina Toegangssleutels naar Kladblok. In een latere stap hebt u beide waarden voor appsettings.json nodig.

Het derde onderdeel is Azure AI Search, dat u in de portal kunt maken of een bestaande zoekservice in uw Azure-resources kunt vinden.

Als u zich wilt verifiëren bij uw zoekservice, hebt u de service-URL en een toegangssleutel nodig.

  1. Meld u aan bij Azure Portal en haal op de pagina Overzicht van de zoekservice de URL op. Een eindpunt ziet er bijvoorbeeld uit als https://mydemo.search.windows.net.

  2. Haal onder Instellingen>Sleutels een beheersleutel op voor volledige rechten op de service. Er zijn twee uitwisselbare beheersleutels die voor bedrijfscontinuïteit worden verstrekt voor het geval u een moet overschakelen. U kunt de primaire of secundaire sleutel gebruiken op aanvragen voor het toevoegen, wijzigen en verwijderen van objecten.

    De naam van de service en de querysleutels voor beheer ophalen

Met een geldige sleutel stelt u per aanvraag een vertrouwensrelatie in tussen de toepassing die de aanvraag verzendt en de service die de aanvraag afhandelt.

2 - De omgeving instellen

  1. Start Visual Studio, en selecteer in het menu Extra de optie NuGet Package Manager en NuGet-pakketten voor oplossing beheren....

  2. Ga naar het tabblad Bladeren. Zoek en installeer vervolgens Azure.Search.Documents (versie 11.0 of hoger).

  3. Ga naar de NuGet-pakketten Microsoft.Extensions.Configuration en Microsoft.Extensions.Configuration.Json en installeer ze.

  4. Open het oplossingsbestand /v11/AzureSearchMultipleDataSources.sln.

  5. Bewerk het bestand appsettings.json in Solution Explorer om verbindingsgegevens op te geven.

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

De eerste twee vermeldingen zijn de URL en beheersleutels van een zoekservice. Gebruik het volledige eindpunt, bijvoorbeeld: https://mydemo.search.windows.net.

In de volgende vermeldingen worden de accountnamen en de verbindingsreeksgegevens van de Azure-blobopslag- en Azure Cosmos DB-gegevensbronnen opgegeven.

3 - Sleutelvelden toewijzen

Voor het samenvoegen van inhoud moeten beide gegevensstromen zijn gericht op dezelfde documenten in de zoekindex.

In Azure AI Search identificeert het sleutelveld elk document uniek. Elke zoekindex moet precies één sleutelveld van het type Edm.String bevatten. Het sleutelveld moet aanwezig zijn voor elk document in een gegevensbron dat wordt toegevoegd aan de index. (Dit is zelfs het enige vereiste veld.)

Wanneer u gegevens van meerdere gegevensbronnen indexeert, zorgt u ervoor dat elke binnenkomende rij of elk binnenkomend document een algemene documentsleutel bevat om gegevens van twee fysiek afzonderlijke brondocumenten samen te voegen in een nieuw zoekdocument in de gecombineerde index.

Vaak moet er op voorhand goed worden gepland om een betekenisvolle documentsleutel voor uw index te verzinnen en ervoor te zorgen dat deze aanwezig is in beide gegevensbronnen. In deze demo is de HotelId sleutel voor elk hotel in Azure Cosmos DB ook aanwezig in de kamers JSON-blobs in Blob Storage.

Azure AI Search-indexeerfuncties kunnen veldtoewijzingen gebruiken om de naam van gegevensvelden te wijzigen en zelfs opnieuw op te maken tijdens het indexeringsproces, zodat brongegevens kunnen worden omgeleid naar het juiste indexveld. In Azure Cosmos DB wordt de hotel-id bijvoorbeeld aangeroepen HotelId. In de JSON-blobbestanden voor de hotelkamers is de hotel-id echter Id. Het programma verwerkt deze discrepantie door het Id veld van de blobs toe te geven aan het HotelId sleutelveld in de indexeerfunctie.

Notitie

In de meeste gevallen zijn automatisch gegenereerde documentsleutels, zoals die standaard worden gemaakt door bepaalde indexeerfuncties, geen goede documentsleutels voor gecombineerde indexen. Over het algemeen moet u een betekenisvolle, unieke sleutelwaarde gebruiken die al bestaat in, of eenvoudig kan worden toegevoegd aan, uw gegevensbronnen.

4 - De code verkennen

Zodra de gegevens en configuratie-instellingen kloppen, kan het voorbeeldprogramma in /v11/AzureSearchMultipleDataSources.sln worden gebouwd en uitgevoerd.

Deze eenvoudige C#-/.NET-console-app voert de volgende taken uit:

  • Maakt een nieuwe index op basis van de gegevensstructuur van de C#-hotelklasse (die ook verwijst naar de adres- en kamerklassen).
  • Maakt een nieuwe gegevensbron en een indexeerfunctie om Azure Cosmos DB-gegevens toe te wijzen aan indexvelden. Dit zijn beide objecten in Azure AI Search.
  • Hiermee wordt de indexeerfunctie uitgevoerd om hotelgegevens uit Azure Cosmos DB te laden.
  • Maakt een tweede gegevensbron en een indexeerfunctie om JSON-blobgegevens toe te wijzen aan indexvelden.
  • Voert de tweede indexeerfunctie uit om kamergegevens uit de blobopslag te laden.

Neem, voordat u het programma gaat uitvoeren, even een minuut de tijd om de code en de index- en indexeerfunctiedefinities voor dit voorbeeld te bestuderen. De relevante code staat in twee bestanden:

  • Hotel.cs bevat het schema dat de index definieert
  • Program.cs bevat functies die de Azure AI Search-index, gegevensbronnen en indexeerfuncties maken en de gecombineerde resultaten in de index laden.

Een index maken

In dit voorbeeldprogramma wordt CreateIndexAsync gebruikt om een Azure AI Search-index te definiëren en te maken. Er wordt gebruikgemaakt van de FieldBuilder-klasse om een indexstructuur te genereren op basis van een C#-gegevensmodelklasse.

Het gegevensmodel wordt gedefinieerd door de hotelklasse, die ook verwijzingen bevat naar de adres- en kamerklassen. Met FieldBuilder wordt ingezoomd op meerdere klassedefinities om een complexe gegevensstructuur voor de index te genereren. Tags voor metagegevens worden gebruikt voor het definiëren van de kenmerken van elk veld; er kan bijvoorbeeld worden aangegeven of een veld doorzoekbaar of sorteerbaar is.

Met het programma worden alle bestaande indexen met dezelfde naam verwijderd, voordat het nieuwe wordt gemaakt (mocht u dit voorbeeld meer dan één keer willen uitvoeren).

In de volgende fragmenten uit het bestand Hotel.cs worden enkele velden weergegeven, gevolgd door een verwijzing naar een andere gegevensmodelklasse, Room[], die op zijn beurt is gedefinieerd in Room.cs bestand (niet weergegeven).

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

In het bestand Program.cs wordt een Zoekindex gedefinieerd met een naam en een veldverzameling, gegenereerd via de methode FieldBuilder.Build. De index wordt hierna als volgt gemaakt:

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

Een Azure Cosmos DB-gegevensbron en -indexeerfunctie maken

Het hoofdprogramma bevat logica om de Azure Cosmos DB-gegevensbron te maken voor de hotelgegevens.

Eerst wordt de naam van de Azure Cosmos DB-database samengevoegd met de verbindingsreeks. Vervolgens wordt een object SearchIndexerDataSourceConnection gedefinieerd.

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

Wanneer de gegevensbron is gemaakt, stelt het programma een Azure Cosmos DB-indexeerfunctie in met de naam hotel-rooms-cosmos-indexer.

Met het programma worden eventuele bestaande indexeerfuncties met dezelfde naam bijgewerkt, waarbij de bestaande indexeerfunctie wordt overschreven door de inhoud van de bovenstaande code. Het omvat ook het opnieuw instellen en uitvoeren van acties, voor het geval u dit voorbeeld meer dan één keer wilt uitvoeren.

In het volgende voorbeeld wordt een schema voor de indexeerfunctie gedefinieerd, zodat deze één keer per dag wordt uitgevoerd. U kunt de planningseigenschap uit deze aanroep verwijderen als u niet wilt dat de indexeerfunctie in de toekomst automatisch opnieuw wordt uitgevoerd.

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

Dit voorbeeld bevat een eenvoudig try-catch-blok om eventuele fouten te rapporteren die tijdens de uitvoering kunnen optreden.

Nadat de Azure Cosmos DB-indexeerfunctie is uitgevoerd, bevat de zoekindex een volledige reeks voorbeelden van hoteldocumenten. Het veld Kamers van elk hotel is echter een lege matrix, omdat de gegevensbron van Azure Cosmos DB geen kamergegevens bevat. Vervolgens haalt het programma gegevens op uit de blobopslag om de kamergegevens te laden en samen te voegen.

Gegevensbron op basis van blobopslag en de indexeerfunctie maken

Voor het ophalen van de kamergegevens stelt het programma eerst een gegevensbron voor de blobopslag in, zodat wordt verwezen naar een set afzonderlijke JSON-blob-bestanden.

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

Wanneer de gegevensbron is gemaakt, stelt het programma een blob-indexeerfunctie in met de naam hotel-rooms-blob-indexer, zoals hieronder weergegeven.

De JSON-blobs bevatten een sleutelveld met de naam Id in plaats van HotelId. In de code wordt de klasse FieldMapping gebruikt om de indexeerfunctie te laten weten dat de veldwaarde Id moet verwijzen naar de documentsleutel HotelId in de index.

Indexeerfuncties voor Blob-opslag kunnen IndexingParameters gebruiken om een parseermodus op te geven. U moet een andere parseermodus instellen afhankelijk van of blobs een enkel document vertegenwoordigen, of meerdere documenten binnen dezelfde blob. In dit voorbeeld vertegenwoordigt elke blob één JSON-document. In de code wordt dus de parameter json gebruikt. Voor meer informatie over het parseren van parameters voor de indexeerfunctie voor JSON-blobs raadpleegt u JSON-blobs indexeren.

In dit voorbeeld wordt een schema voor de indexeerfunctie gedefinieerd zodat deze een keer per dag wordt uitgevoerd. U kunt de planningseigenschap uit deze aanroep verwijderen als u niet wilt dat de indexeerfunctie in de toekomst automatisch opnieuw wordt uitgevoerd.

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

Omdat de index al is gevuld met hotelgegevens uit de Azure Cosmos DB-database, werkt de blobindexeerfunctie de bestaande documenten in de index bij en worden de kamergegevens toegevoegd.

Notitie

Als u dezelfde niet-sleutelvelden in beide gegevensbronnen hebt en de gegevens in deze velden niet overeenkomen, bevat de index de waarden van de indexeerfunctie die het meest recent is uitgevoerd. In ons voorbeeld bevatten beide gegevensbronnen het veld HotelName. Als de gegevens in dit veld om de een of andere reden verschillen, worden voor documenten met dezelfde sleutelwaarde de HotelName-gegevens uit de gegevensbron die het laatst is geïndexeerd opgeslagen in de index.

U kunt de gevulde zoekindex onderzoeken nadat het programma is uitgevoerd. Gebruik hiervoor Search Explorer in de portal.

Open in Azure Portal de pagina Overzicht van de zoekservice en zoek in de lijst Indexen de index hotel-rooms-sample.

Lijst met Azure AI Search-indexen

Selecteer in de lijst de index hotel-rooms-sample. U ziet een Search Explorer-interface voor de index. Voer een query in voor een term, bijvoorbeeld luxe. Er wordt ten minste één document in de resultaten weergegeven. In dit document staat een lijst met kamerobjecten in de kamermatrix.

Opnieuw instellen en uitvoeren

In de vroege experimentele ontwikkelingsfasen is de meest praktische benadering voor het ontwerpen van iteratie het verwijderen van de objecten uit Azure AI Search en het mogelijk maken van uw code om ze opnieuw te bouwen. Resourcenamen zijn uniek. Na het verwijderen van een object kunt u het opnieuw maken met dezelfde naam.

In de voorbeeldcode wordt gecontroleerd op bestaande objecten, en worden deze verwijderd of bijgewerkt, zodat u het programma opnieuw kunt uitvoeren.

U kunt de portal gebruiken om indexen, indexeerfuncties en gegevensbronnen te verwijderen.

Resources opschonen

Wanneer u in uw eigen abonnement werkt, is het een goed idee om aan het einde van een project te bepalen of u de gemaakte resources nog steeds nodig hebt en of u deze moet verwijderen. Resources die actief blijven, kunnen u geld kosten. U kunt resources afzonderlijk verwijderen, maar u kunt ook de resourcegroep verwijderen als u de volledige resourceset wilt verwijderen.

U kunt resources vinden en beheren in de portal via de koppeling Alle resources of Resourcegroepen in het navigatiedeelvenster aan de linkerkant.

Volgende stappen

Nu u bekend bent met het concept van het opnemen van gegevens uit meerdere bronnen, gaan we de configuratie van de indexeerfunctie nader bekijken, te beginnen met Azure Cosmos DB.