Indexer des données à partir du Stockage Table Azure

Dans cet article, découvrez comment configurer un indexeur qui importe du contenu du Stockage Table Azure et le rend interrogeable dans la Recherche Azure AI. Les entrées de l’indexeur sont vos entités, dans une même table. La sortie est un index de recherche avec du contenu et des métadonnées pouvant faire l’objet de recherches stockés dans des champs individuels.

Cet article est un complément de Créer un indexeur avec des informations spécifiques de l’indexation à partir du Stockage Table Azure. Il utilise les API REST pour illustrer un workflow en trois parties commun à tous les indexeurs : créer une source de données, créer un index, créer un indexeur. L’extraction de données se produit quand vous envoyez la demande de création d’un indexeur.

Prérequis

  • Azure Table Storage

  • Des tables contenant du texte. Si vous avez des données binaires, vous pouvez utiliser l’enrichissement par IA pour l’analyse des images.

  • Autorisations de lecture sur Stockage Azure. Une chaîne de connexion « accès total » inclut une clé qui accorde l’accès au contenu, mais si vous utilisez des rôles Azure, vérifiez que l’identité managée du service de recherche dispose des autorisations Données et Lecteur.

  • Utilisez un client REST pour formuler des appels REST semblables à ceux présentés dans cet article.

Définir la source de données

La définition de la source de données spécifie les données sources à indexer, les informations d’identification et les stratégies pour la détection des changements. Une source de données est une ressource indépendante pouvant être utilisée par plusieurs indexeurs.

  1. Créez ou mettez à jour une source de données pour régler sa définition :

     POST https://[service name].search.windows.net/datasources?api-version=2023-11-01 
     {
         "name": "my-table-storage-ds",
         "description": null,
         "type": "azuretable",
         "subtype": null,
         "credentials": {
            "connectionString": "DefaultEndpointsProtocol=https;AccountName=<account name>"
         },
         "container": {
            "name": "my-table-in-azure-storage",
            "query": ""
         },
         "dataChangeDetectionPolicy": null,
         "dataDeletionDetectionPolicy": null,
         "encryptionKey": null,
         "identity": null
     }
    
  2. Définissez « type » sur "azuretable" (obligatoire).

  3. Définissez « credentials » sur une chaîne de connexion Stockage Azure. La section suivante décrit les formats pris en charge.

  4. Définissez « container » sur le nom de la table.

  5. Si vous le souhaitez, définissez « query » sur un filtre sur PartitionKey. La définition de cette propriété est une bonne pratique qui améliore les performances. Si « query » est null, l’indexeur exécute une analyse de table complète, ce qui entraîne une dégradation des performances si les tables sont grandes.

Une définition de source de données peut également inclure des stratégies de suppression réversible si vous souhaitez que l’indexeur supprime un document de recherche lorsque le document source est marqué pour suppression.

Informations d’identification et chaînes de connexion prises en charge

Les indexeurs peuvent se connecter à une table à l’aide des connexions suivantes.

Chaîne de connexion au compte de stockage avec accès complet
{ "connectionString" : "DefaultEndpointsProtocol=https;AccountName=<your storage account>;AccountKey=<your account key>;" }
Vous pouvez obtenir la chaîne de connexion à partir de la page du compte de stockage dans Portail Azure en sélectionnant Clés d’accès dans le volet de navigation de gauche. Veillez à sélectionner une chaîne de connexion complète et pas seulement une clé.
Chaîne de connexion d’identité managée
{ "connectionString" : "ResourceId=/subscriptions/<your subscription ID>/resourceGroups/<your resource group name>/providers/Microsoft.Storage/storageAccounts/<your storage account name>/;" }
Cette chaîne de connexion ne nécessite pas de clé de compte, mais vous devez avoir préalablement configuré un service de recherche pour la connexion avec une identité managée.
Chaîne de connexion de la signature d’accès partagé** (SAP) au compte de stockage
{ "connectionString" : "BlobEndpoint=https://<your account>.blob.core.windows.net/;SharedAccessSignature=?sv=2016-05-31&sig=<the signature>&spr=https&se=<the validity end time>&srt=co&ss=b&sp=rl;" }
La SAP doit avoir les autorisations de liste et lecture sur les tables et les entités.
Signature d’accès partagé du conteneur
{ "connectionString" : "ContainerSharedAccessUri=https://<your storage account>.blob.core.windows.net/<container name>?sv=2016-05-31&sr=c&sig=<the signature>&se=<the validity end time>&sp=rl;" }
La SAP doit avoir les autorisations de liste et lecture sur le conteneur. Pour plus d’informations, consultez Utilisation des signatures d’accès partagé.

Remarque

Si vous utilisez des informations d’identification SAS, vous devez mettre à jour les informations d’identification de la source de données régulièrement avec des signatures renouvelées pour éviter qu’elles expirent. Si les informations d’identification SAS expirent, l’indexeur échoue avec un message d’erreur de type « Les informations d’identification fournies dans la chaîne de connexion ne sont pas valides ou ont expiré ».

Partition pour améliorer les performances

Par défaut, la Recherche Azure AI utilise le filtre de requête interne suivant pour effectuer le suivi des entités sources qui ont été mises à jour depuis la dernière exécution : Timestamp >= HighWaterMarkValue. Dans la mesure où les tables Azure n’ont pas d’index secondaire sur le champ Timestamp, ce type de requête nécessite une analyse de table complète et est donc lente pour les tables volumineuses.

Pour éviter une analyse complète, vous pouvez utiliser des partitions de table pour réduire l’étendue de chaque travail d’indexeur.

  • Si vos données peuvent être partitionnées naturellement en plusieurs plages de partition, créez une source de données et un indexeur correspondant pour chaque plage. Maintenant, chaque indexeur n’a à traiter qu’une plage de partition spécifique, ce qui conduit à de meilleures performances pour les requêtes. Si les données à indexer ont un petit nombre de partitions fixes, c’est encore mieux : chaque indexeur procède uniquement à une analyse de partition.

    Par exemple, pour créer une source de données permettant de traiter une plage de partitions dont les clés vont de 000 à 100, utilisez une requête semblable à celle-ci : "container" : { "name" : "my-table", "query" : "PartitionKey ge '000' and PartitionKey lt '100' " }.

  • Si vos données sont partitionnées par date (par exemple, si vous créez une nouvelle partition chaque jour ou chaque semaine), envisagez l’approche suivante :

    • Dans la définition de la source de données, spécifiez une requête semblable à l’exemple suivant : (PartitionKey ge <TimeStamp>) and (other filters).

    • Surveillez la progression de l’indexeur avec l’API Get Indexer Status et mettez régulièrement à jour la condition <TimeStamp> de la requête sur la base de la dernière valeur de limite supérieure réussie.

    • Avec cette approche, si vous devez déclencher une réindexation complète, réinitialisez la requête de la source de données en plus de l’indexeur.

Ajouter des champs de recherche à un index

Dans un index de recherche, ajoutez des champs pour accepter le contenu et les métadonnées des entités de votre table.

  1. Créez ou mettez à jour un index pour définir les champs de recherche qui stockeront le contenu des entités :

    POST https://[service name].search.windows.net/indexes?api-version=2023-11-01 
    {
      "name" : "my-search-index",
      "fields": [
        { "name": "Key", "type": "Edm.String", "key": true, "searchable": false },
        { "name": "SomeColumnInMyTable", "type": "Edm.String", "searchable": true }
      ]
    }
    
  2. Créez un champ de clé de document ("key": true), mais laissez l’indexeur le remplir automatiquement. Un indexeur de table remplit le champ de clé avec les clés de partition et de ligne concaténées de la table. Par exemple, si la valeur PartitionKey d’une ligne est 1 et que RowKey est 1_123, alors la valeur de la clé est 11_123. Si la clé de partition est null, seule la clé de ligne est utilisée.

    Si vous utilisez l’Assistant Importation de données pour créer l’index, le portail déduit un champ « Key » pour l’index de recherche, et utilise un mappage de champs implicite pour connecter les champs sources et de destination. Vous n’avez pas besoin d’ajouter le champ vous-même ni de configurer un mappage de champs.

    Si vous utilisez les API REST et voulez des mappages de champs implicites, créez le champ de clé de document et nommez-le « Key » dans la définition d’index de recherche, comme indiqué à l’étape précédente ({ "name": "Key", "type": "Edm.String", "key": true, "searchable": false }). L’indexeur remplit automatiquement le champ Key, sans mappage de champs.

    Si vous ne souhaitez pas d’un champ nommé « Key » dans votre index de recherche, ajoutez un mappage de champs explicite dans la définition de l’indexeur avec le nom de champ souhaité, en définissant le champ source sur « Key » :

     "fieldMappings" : [
       {
         "sourceFieldName" : "Key",
         "targetFieldName" : "MyDocumentKeyFieldName"
       }
    ]
    
  3. Ajoutez maintenant tous les autres champs d’entité souhaités dans votre index. Par exemple, si une entité ressemble à l’exemple suivant, votre index de recherche doit avoir des champs correspondant à HotelName, Description et Category pour pouvoir recevoir ces valeurs.

    Capture d’écran du contenu du tableau dans le navigateur de stockage.

    L’utilisation des mêmes noms et de types de données compatibles réduit le besoin de mappage des champs. Quand les noms et les types sont identiques, l’indexeur peut déterminer automatiquement le chemin des données.

Configurer et exécuter l’indexeur de table

Dès que vous avez un index et une source de données, vous êtes prêt à créer l’indexeur. La configuration de l’indexeur spécifie les entrées, les paramètres et les propriétés qui contrôlent les comportements d’exécution.

  1. Créez ou mettez à jour un indexeur en lui attribuant un nom, et en référençant la source de données et l’index cible :

    POST https://[service name].search.windows.net/indexers?api-version=2023-11-01
    {
        "name" : "my-table-indexer",
        "dataSourceName" : "my-table-storage-ds",
        "targetIndexName" : "my-search-index",
        "disabled": null,
        "schedule": null,
        "parameters" : {
            "batchSize" : null,
            "maxFailedItems" : null,
            "maxFailedItemsPerBatch" : null,
            "base64EncodeKeys" : null,
            "configuration" : { }
        },
        "fieldMappings" : [ ],
        "cache": null,
        "encryptionKey": null
    }
    
  2. Spécifiez les mappages de champs s’il existe des différences dans le nom ou le type du champ, ou si vous avez besoin de plusieurs versions d’un champ source dans l’index de recherche. Le champ Target est le nom du champ dans l’index de recherche.

     "fieldMappings" : [
       {
         "sourceFieldName" : "Description",
         "targetFieldName" : "HotelDescription"
       }
    ]
    
  3. Pour plus d’informations sur les autres propriétés, consultez Créer un indexeur.

Un indexeur s’exécute automatiquement quand il est créé. Vous pouvez l’éviter en définissant « disabled » sur true. Pour contrôler l’exécution de l’indexeur, exécutez un indexeur à la demande ou placez-le dans une planification.

Vérifier l’état de l’indexeur

Pour monitorer l’état de l’indexeur et l’historique d’exécution, envoyez une demande Obtenir l’état de l’indexeur :

GET https://myservice.search.windows.net/indexers/myindexer/status?api-version=2023-11-01
  Content-Type: application/json  
  api-key: [admin key]

La réponse comprend l’état et le nombre d’éléments traités. Le résultat doit ressembler à l’exemple suivant :

    {
        "status":"running",
        "lastResult": {
            "status":"success",
            "errorMessage":null,
            "startTime":"2023-02-21T00:23:24.957Z",
            "endTime":"2023-02-21T00:36:47.752Z",
            "errors":[],
            "itemsProcessed":1599501,
            "itemsFailed":0,
            "initialTrackingState":null,
            "finalTrackingState":null
        },
        "executionHistory":
        [
            {
                "status":"success",
                "errorMessage":null,
                "startTime":"2023-02-21T00:23:24.957Z",
                "endTime":"2023-02-21T00:36:47.752Z",
                "errors":[],
                "itemsProcessed":1599501,
                "itemsFailed":0,
                "initialTrackingState":null,
                "finalTrackingState":null
            },
            ... earlier history items
        ]
    }

L’historique d’exécution contient jusqu’à 50 exécutions les plus récentes, classées par ordre chronologique inversé, la dernière exécution apparaissant en premier.

Étapes suivantes

En savoir plus sur l’exécution de l’indexeur, le monitoring de l’état ou la planification d’exécution de l’indexeur. Les articles suivants s’appliquent aux indexeurs qui extraient du contenu de Stockage Azure :