Compartir a través de


Tutorial: Indexación de varios orígenes de datos mediante el SDK de .NET

Azure AI Search admite la importación, el análisis y la indexación de datos de varios orígenes de datos en un único índice de búsqueda consolidado.

En este tutorial de C# se usa la biblioteca cliente Azure.Search.Documents del SDK de Azure para .NET para indexar datos de hotel de ejemplo desde una instancia de Azure Cosmos DB. A continuación, combinará los datos con los detalles de la habitación del hotel extraídos de los documentos de Azure Blob Storage. El resultado es un índice combinado de búsqueda de hoteles que contiene documentos de hotel, con habitaciones como tipos de datos complejos.

En este tutorial, usted hará lo siguiente:

  • Cargar datos de muestra en fuentes de datos
  • Identificar la clave del documento
  • Definir y crear el índice
  • Indexar los datos de los hoteles desde Azure Cosmos DB
  • Combinar datos de habitaciones de hotel desde Blob Storage

Información general

En este tutorial se usa Azure.Search.Documents, versión 11.x, para crear y ejecutar varios indexadores. Los datos de ejemplo se cargan en dos orígenes de datos de Azure y se configura un indexador que extrae de ambos orígenes para rellenar un único índice de búsqueda. Los dos conjuntos de datos deben tener un valor en común para admitir la combinación. En este tutorial, ese campo es un identificador. Siempre que haya un campo común para admitir el mapeo, un indexador puede fusionar datos de recursos dispares: datos estructurados de Azure SQL, datos no estructurados de Blob Storage o cualquier combinación de orígenes de datos admitidos en Azure.

En el proyecto siguiente se puede encontrar una versión finalizada del código de este tutorial:

Requisitos previos

Nota:

Puede usar un servicio de búsqueda gratuito para este tutorial. El nivel gratis le limita a tres índices, tres indexadores y tres orígenes de datos. En este tutorial se crea uno de cada uno. Antes de empezar, asegúrese de que tiene espacio en el servicio para aceptar los nuevos recursos.

Preparación de servicios

En este tutorial se usa Azure AI Search para indexación y consultas, Azure Cosmos DB para el primer conjunto de datos y Azure Blob Storage para el segundo conjunto de datos.

Si es posible, cree todos los servicios en la misma región y grupo de recursos por proximidad y capacidad de administración. En la práctica, los servicios pueden estar en cualquier región.

En este ejemplo se usan dos pequeños conjuntos de datos que describen siete hoteles ficticios. Un conjunto describe los propios hoteles y se cargará en una base de datos de Azure Cosmos DB. El otro conjunto contiene los detalles de la habitación del hotel y se proporciona como siete archivos JSON independientes que se van a cargar en Azure Blob Storage.

Comenzar con Azure Cosmos DB

  1. Inicie sesión en Azure Portal y seleccione la cuenta de Azure Cosmos DB.

  2. En el panel izquierdo, seleccione Explorador de datos.

  3. Seleccione Nuevo Contenedor>Nueva Base de Datos.

    Creación de una base de datos

  4. Escriba hotel-rooms-db como nombre. Acepte los valores predeterminados para el resto de la configuración.

    Configuración de la base de datos

  5. Cree un contenedor destinado a la base de datos que creó anteriormente. Escriba hoteles para el nombre del contenedor y /HotelId para la clave de partición.

    Agregar contenedor

  6. Seleccione hotels>Items (Elementos) y, a continuación, seleccione Upload Item (Cargar elemento ) en la barra de comandos.

  7. Cargue el archivo JSON desde la cosmosdb carpeta en multiple-data-sources/v11.

    Cargar en la colección de Azure Cosmos DB

  8. Utiliza el botón Actualizar para actualizar la vista de los elementos de la colección de hoteles. Verá siete nuevos documentos de base de datos enumerados.

  9. En el panel izquierdo, seleccione Configuración>Claves.

  10. Tome nota de una cadena de conexión. Necesita este valor para appsettings.json en un paso posterior. Si no usó el nombre sugerido de la base de datos hotel-rooms-db , copie también el nombre de la base de datos.

Azure Blob Storage

  1. Inicie sesión en Azure Portal y seleccione la cuenta de Azure Storage.

  2. En el panel izquierdo, seleccioneContenedores>.

  3. Cree un contenedor de blobs denominado hotel-rooms para almacenar los archivos JSON de las habitaciones de hotel de ejemplo. Puede establecer el nivel de acceso en cualquier valor válido.

    Creación de un contenedor de blobs

  4. Abra el contenedor y seleccione Cargar en la barra de comandos.

  5. Cargue los siete archivos JSON de la blob carpeta en multiple-data-sources/v11.

    Carga de archivos

  6. En el panel izquierdo, seleccione Seguridad y clavesde> red.

  7. Anote el nombre de la cuenta y una cadena de conexión. Necesita ambos valores para appsettings.json en un paso posterior.

El tercer componente es Azure AI Search, que puedes crear en Azure Portal o buscar en un servicio de búsqueda existente en recursos de Azure.

Para autenticarse en el servicio de búsqueda, necesita la dirección URL del servicio y una clave de acceso. Tener una clave válida establece la confianza por solicitud entre la aplicación que envía la solicitud y el servicio que lo controla.

  1. Inicie sesión en Azure Portal y seleccione el servicio de búsqueda.

  2. En el panel izquierdo, seleccione Información general.

  3. Anote la dirección URL, que debería tener un aspecto similar a https://my-service.search.windows.net.

  4. En el panel izquierdo, seleccione Configuración>Claves.

  5. Anote una clave de administrador para obtener derechos completos en el servicio. Se proporcionan dos claves de administrador intercambiables para lograr la continuidad empresarial, por si necesitara sustituir una de ellas. Puede usar cualquiera de las claves para solicitudes de agregar, modificar y eliminar objetos.

Configuración del entorno

  1. Abra el AzureSearchMultipleDataSources.sln archivo desde multiple-data-sources/v11 en Visual Studio.

  2. En el Explorador de soluciones, haga clic con el botón derecho en el proyecto y seleccione Administrar paquetes NuGet para la solución....

  3. En la pestaña Examinar , busque e instale los siguientes paquetes:

    • Azure.Search.Documents (versión 11.0 o posterior)

    • Microsoft.Extensions.Configuration

    • Microsoft.Extensions.Configuration.Json

  4. En el Explorador de soluciones, edite el appsettings.json archivo con la información de conexión que recopiló en los pasos anteriores.

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

Mapear campos clave

La combinación de contenido requiere que ambos flujos de datos tengan como destino los mismos documentos en el índice de búsqueda.

En Azure AI Search, el campo de clave identifica de manera exclusiva cada documento. Cada índice de búsqueda debe tener exactamente un campo clave de tipo Edm.String. Ese campo de clave debe estar presente para cada documento de un origen de datos que se agregue al índice. (de hecho, es el único campo obligatorio).

Al indexar datos de varios orígenes de datos, asegúrese de que cada fila o documento entrante contiene una clave de documento común. Esto le permite combinar datos de dos documentos de origen físicamente distintos en un nuevo documento de búsqueda en el índice combinado.

A menudo, requiere algún planeamiento inicial para identificar una clave de documento significativa para el índice y asegurarse de que existe en ambos orígenes de datos. En esta demostración, la clave HotelId de cada hotel de Azure Cosmos DB también está presente en las salas de blobs JSON de Blob Storage.

Los indexadores de Azure AI Search pueden usar asignaciones de campo para cambiar el nombre e incluso el formato de campos de datos durante la indexación para poder dirigir los datos de origen al campo de índice correcto. Por ejemplo, en Azure Cosmos DB, el identificador de hotel se denomina HotelId, pero en los archivos de blob JSON para las habitaciones del hotel, el identificador del hotel se denomina Id. El programa se encarga de esta discrepancia mediante la asignación del campo Id desde los blobs hasta el campo de clave HotelId del indexador.

Nota:

En la mayoría de los casos, las claves de documento generadas automáticamente, como las creadas de forma predeterminada por algunos indexadores, no hacen buenas claves de documento para índices combinados. En general, use un valor de clave único significativo que ya exista en los orígenes de datos o se pueda agregar fácilmente.

Exploración del código

Cuando los datos y las opciones de configuración están en vigor, el programa de ejemplo de AzureSearchMultipleDataSources.sln debe estar listo para compilar y ejecutarse.

Esta sencilla aplicación de consola de C#/.NET realiza las siguientes tareas:

  • Crea un nuevo índice basado en la estructura de datos de la clase Hotel de C#, que también hace referencia a las clases Address y Room.
  • Crea un nuevo origen de datos y un indexador que asigna los datos de Azure Cosmos DB a campos de índice. Ambos son objetos de Azure AI Search.
  • Ejecuta el indexador para cargar datos de hotel desde Azure Cosmos DB.
  • Crea un segundo origen de datos y un indexador que asigna datos de blob JSON a campos de índice.
  • Ejecuta el segundo indexador para cargar los datos de la sala de hotel desde Blob Storage.

Antes de ejecutar el programa, dedique un minuto a estudiar el código, la definición de índice y la definición del indexador. El código pertinente aparece en dos archivos:

  • Hotel.cs contiene el esquema que define el índice.
  • Program.cs contiene funciones que crean el índice, los orígenes de datos y los indexadores de Azure AI Search y cargan los resultados combinados en el índice.

Creación de un índice

Este programa de ejemplo usa CreateIndexAsync para definir y crear un índice de Azure AI Search. Aprovecha la clase FieldBuilder para generar una estructura de índice a partir de una clase de modelo de datos de C#.

El modelo de datos se define mediante la clase Hotel, que también contiene referencias a las clases Address y Room. FieldBuilder explora en profundidad varias definiciones de clase para generar una estructura de datos compleja para el índice. Se usan etiquetas de metadatos para definir los atributos de cada campo (por ejemplo, si permiten hacer búsquedas o clasificaciones).

El programa elimina cualquier índice existente del mismo nombre antes de crear el nuevo, en caso de que desee ejecutar este ejemplo más de una vez.

Los fragmentos de código siguientes del Hotel.cs archivo muestran campos únicos, seguidos de una referencia a otra clase de modelo de datos, Room[], que a su vez se define en Room.cs el archivo (no se muestra).

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

En el Program.cs archivo, searchIndex se define con un nombre y una colección de campos generada por el FieldBuilder.Build método y, a continuación, se crea como se indica a continuación:

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

Creación de un origen de datos de Azure Cosmos DB y de un indexador

El programa principal incluye lógica para crear el origen de datos de Azure Cosmos DB para los datos de hoteles.

En primer lugar, concatena el nombre de la base de datos de Azure Cosmos DB en la cadena de conexión. A continuación, define un 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);

Una vez creado el origen de datos, el programa configura un indexador de Azure Cosmos DB denominado hotel-rooms-cosmos-indexer.

El programa actualiza cualquier indexador existente con el mismo nombre, sobrescribiendo el indexador actual con el contenido del código anterior. También incluye acciones de restablecimiento y ejecución, por si desea ejecutar este ejemplo más de una vez.

En el ejemplo siguiente se define una programación para el indexador, de modo que se ejecute una vez al día. Puede quitar la propiedad de programación de esta llamada si no desea que el indexador se vuelva a ejecutar automáticamente en el 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 ejemplo incluye un bloque sencillo try-catch para notificar los errores que puedan producirse durante la ejecución.

Una vez que se ejecuta el indexador de Azure Cosmos DB, el índice de búsqueda contiene un conjunto completo de documentos de hotel de ejemplo. Sin embargo, el campo de habitaciones de cada hotel es una matriz vacía, ya que el origen de datos de Azure Cosmos DB omite los detalles de las habitaciones. A continuación, el programa obtiene datos de Blob Storage para cargar y fusionar la información de la sala.

Creación de un origen de datos e indexador de Blob Storage

Para obtener los detalles de la sala, el programa configura primero un origen de datos de Blob Storage para hacer referencia a un conjunto de archivos de blob JSON individuales.

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

Una vez creado el origen de datos, el programa configura un indexador de blobs denominado hotel-rooms-blob-indexer, como se muestra a continuación.

Los blobs JSON contienen un campo de clave denominado Id en lugar de HotelId. El código usa la clase FieldMapping para indicar al indexador que dirija el valor del campo Id a la clave de documento HotelId del índice.

Los indexadores de Blob Storage pueden usar IndexingParameters para especificar un modo de análisis. Debe establecer diferentes modos de análisis en función de si los blobs representan un único documento o varios documentos dentro del mismo blob. En este ejemplo, cada blob representa un documento de JSON único, por lo que el código usa el modo de análisis json. Para más información sobre los parámetros de análisis del indexador, consulte el artículo sobre la Indexación de blobs JSON.

En este ejemplo se define una programación para el indexador, de modo que se ejecute una vez al día. Puede quitar la propiedad de programación de esta llamada si no desea que el indexador se vuelva a ejecutar automáticamente en el 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);
}

Dado que el índice ya se ha rellenado con datos de hotel de la base de datos de Azure Cosmos DB, el indexador de blobs actualiza los documentos existentes en el índice y agrega los detalles de la sala.

Nota:

Si tiene los mismos campos que no son clave en ambos orígenes de datos y los datos de esos campos no coinciden, el índice contiene los valores de cada vez que se ejecutó el indexador más recientemente. En nuestro ejemplo, ambos orígenes de datos contienen un HotelName campo . Si por algún motivo los datos de este campo son diferentes, para los documentos con el mismo valor de clave, los HotelName datos del origen de datos indexado más recientemente son el valor almacenado en el índice.

Después de ejecutar el programa, puede explorar el índice de búsqueda rellenado mediante el Explorador de búsqueda en Azure Portal.

  1. Inicie sesión en Azure Portal y seleccione el servicio de búsqueda.

  2. En el panel izquierdo, seleccione Índices de administración de> búsqueda.

  3. Seleccione hotel-rooms-sample en la lista de índices.

  4. En la pestaña Explorador de búsqueda , escriba una consulta para un término como Luxury.

    Tienes que ver al menos un documento en los resultados. Este documento debe contener una lista de objetos de sala en su matriz Rooms.

Restablecer y volver a ejecutar

En las primeras etapas experimentales de desarrollo, el enfoque más práctico para la iteración de diseño es eliminar los objetos de Azure AI Search y permitir que el código vuelva a generarlos. Los nombres de los recursos son únicos. La eliminación de un objeto permite volver a crearlo con el mismo nombre.

En el código de ejemplo se comprueban los objetos existentes y se eliminan o se actualizan para que pueda volver a ejecutar el programa. También puede usar Azure Portal para eliminar los índices, indexadores y orígenes de datos.

Limpieza de recursos

Cuando trabaje con su propia suscripción, al final de un proyecto, es recomendable eliminar los recursos que ya no necesite. Los recursos que se dejan en ejecución pueden costarle mucho dinero. Puede eliminar los recursos de forma individual o eliminar el grupo de recursos para eliminar todo el conjunto de recursos.

Puede encontrar y administrar recursos en Azure Portal mediante el vínculo Todos los recursos o grupos de recursos en el panel izquierdo.

Paso siguiente

Ahora que está familiarizado con la ingesta de datos de varios orígenes, eche un vistazo más a la configuración del indexador, empezando por Azure Cosmos DB: