Mettre à jour ou reconstruire un index dans Recherche IA Azure
Cet article explique comment mettre à jour un index existant dans Recherche IA Azure avec des modifications de schéma ou des modifications de contenu via l’indexation incrémentielle. Il décrit les circonstances dans lesquelles les reconstructions sont nécessaires et fournit des recommandations pour atténuer les effets des reconstructions sur les demandes de requête en cours.
Pendant le développement actif, il est courant de supprimer et regénérer des index quand vous itérez sur une conception d’index. La plupart des développeurs utilisent un petit échantillon représentatif de leurs données pour accélérer la réindexation.
Pour les modifications de schéma sur les applications déjà en production, nous vous recommandons de créer et de tester un nouvel index qui s’exécute côte à côte d’un index existant. Utilisez un alias d’index pour échanger dans le nouvel index afin d’éviter d’avoir à modifier le code de votre application.
Mettre à jour le contenu
L’indexation incrémentielle et la synchronisation d’un index par rapport aux modifications apportées aux données sources sont fondamentales pour la plupart des applications de recherche. Cette section explique le flux de travail pour la mise à jour du contenu de champ dans un index de recherche via l’API REST, mais les kits SDK Azure fournissent une fonctionnalité équivalente.
Le corps de la requête contient un ou plusieurs documents à indexer. Les documents sont identifiés par une clé unique respectant la casse. Chaque document est associé à une action : « upload », « delete », « merge » ou « mergeOrUpload ». Les demandes de téléchargement doivent inclure les données du document sous forme de paires clé/valeur.
{
"value": [
{
"@search.action": "upload (default) | merge | mergeOrUpload | delete",
"key_field_name": "unique_key_of_document", (key/value pair for key field from index schema)
"field_name": field_value (key/value pairs matching index schema)
...
},
...
]
}
Tout d’abord, utilisez les API de chargement de documents, telles que Documents – Index (REST) ou une API équivalente dans les kits SDK Azure. Pour plus d’informations sur les techniques d’indexation, consultez Charger des documents.
Pour une mise à jour volumineuse, le traitement par lot (jusqu’à 1000 documents par lot, ou environ 16 Mo par lot, selon la limite rencontrée en premier) est recommandé car il améliore considérablement les performances d’indexation.
Définissez le paramètre
@search.action
sur l’API pour déterminer l’effet sur les documents existants.Action Effet delete Supprime l’intégralité du document de l’index. Si vous souhaitez supprimer un champ individuel, utilisez plutôt fusionner en définissant le champ en question sur Null. Les documents et les champs supprimés ne libèrent pas immédiatement de l’espace dans l’index. Toutes les quelques minutes, un processus en arrière-plan effectue la suppression physique. Que vous utilisiez le portail Azure ou une API pour retourner des statistiques d’index, vous pouvez vous attendre à un petit délai avant que la suppression ne soit reflétée dans le portail et via les API. merge Met à jour un document qui existe déjà et échoue un document introuvable. Merge remplace les valeurs existantes. Pour cette raison, veillez à rechercher les champs de collection qui contiennent plusieurs valeurs, telles que les champs de type Collection(Edm.String)
. Par exemple, si un champtags
commence par la valeur["budget"]
et que vous exécutez une fusion avec la valeur["economy", "pool"]
, la valeur finale du champtags
est["economy", "pool"]
. Il ne s’agit pas de["budget", "economy", "pool"]
.
Le même comportement s’applique aux collections complexes. Si le document contient un champ de collection complexe nommé Rooms avec la valeur[{ "Type": "Budget Room", "BaseRate": 75.0 }]
, et que vous exécutez une fusion avec une valeur[{ "Type": "Standard Room" }, { "Type": "Budget Room", "BaseRate": 60.5 }]
, la valeur finale du champ Rooms sera[{ "Type": "Standard Room" }, { "Type": "Budget Room", "BaseRate": 60.5 }]
. Cela n’ajoutera pas ou ne fusionnera pas de valeurs nouvelles et existantes.mergeOrUpload Se comporte comme fusion si le document existe et charge si le document est nouveau. Il s’agit de l’action la plus courante pour les mises à jour incrémentielles. upload Similaire à un « upsert » où le document est inséré s’il est nouveau et mis à jour ou remplacé s’il existe. Si les valeurs requises par l’index sont manquantes dans le document, la valeur du champ du document est définie sur Null.
Les requêtes continuent à s’exécuter durant l’indexation, mais si vous mettez à jour ou supprimez des champs existants, vous pouvez vous attendre à des résultats mixtes et à une incidence plus élevée de limitation.
Remarque
Il n’existe aucune garantie de classement quant à l’action dans le corps de la requête qui sera exécutée en premier. Il n’est pas recommandé d’avoir plusieurs actions de « fusion » associées au même document dans un corps de requête unique. S’il existe plusieurs actions de « fusion » requises pour le même document, effectuez la fusion côté client avant de mettre à jour le document dans l’index de recherche.
Réponses
Le code d’état 200 est retourné pour une réponse correcte, ce qui signifie que tous les éléments ont été stockés durablement et commenceront à être indexés. L’indexation s’exécute en arrière-plan et rend les nouveaux documents disponibles (c’est-à-dire, interrogeables et pouvant faire l’objet d’une recherche) quelques secondes après la fin de l’opération d’indexation. Le délai spécifique dépend de la charge sur le service.
Une indexation réussie est indiquée par le fait que la propriété d’état est définie sur true pour tous les éléments, et que la propriété statusCode
est définie sur 201 (pour les documents nouvellement chargés) ou sur 200 (pour les documents fusionnés ou supprimés) :
{
"value": [
{
"key": "unique_key_of_new_document",
"status": true,
"errorMessage": null,
"statusCode": 201
},
{
"key": "unique_key_of_merged_document",
"status": true,
"errorMessage": null,
"statusCode": 200
},
{
"key": "unique_key_of_deleted_document",
"status": true,
"errorMessage": null,
"statusCode": 200
}
]
}
Un code d’état 207 est retourné lorsqu’au moins un élément n’a pas été correctement indexé. Le champ d’état des éléments qui n’ont pas été indexés prend la valeur false. Les propriétés errorMessage
et statusCode
indiquent la raison de l’erreur d’indexation :
{
"value": [
{
"key": "unique_key_of_document_1",
"status": false,
"errorMessage": "The search service is too busy to process this document. Please try again later.",
"statusCode": 503
},
{
"key": "unique_key_of_document_2",
"status": false,
"errorMessage": "Document not found.",
"statusCode": 404
},
{
"key": "unique_key_of_document_3",
"status": false,
"errorMessage": "Index is temporarily unavailable because it was updated with the 'allowIndexDowntime' flag set to 'true'. Please try again later.",
"statusCode": 422
}
]
}
La propriété errorMessage
indique la raison de l’erreur d’indexation, si possible.
Le tableau suivant décrit, par document, les différents codes d’état pouvant être retournés dans la réponse. Certains codes d’état indiquent des problèmes au niveau de la requête proprement dite, tandis que d’autres indiquent des conditions d’erreur temporaires. Dans ce dernier cas, il est recommandé de réessayer l’opération après un certain délai.
Code d’état | Signification | Nouvelle tentative possible | Notes |
---|---|---|---|
200 | Le document a été correctement modifié ou supprimé. | n/a | Les opérations de suppression sont idempotentes. Autrement dit, même si une clé de document n’existe pas dans l’index, toute tentative de suppression à l’aide de cette clé génère le code d’état 200. |
201 | Le document a été créé avec succès. | n/a | |
400 | Le document a rencontré une erreur qui a empêché son indexation. | Non | Le message d’erreur dans la réponse indique le problème survenu au niveau du document. |
404 | Le document n’a pas pu être fusionné, car la clé spécifiée n’existe pas dans l’index. | Non | Cette erreur ne s’applique pas aux téléchargements, dans la mesure où ils créent de nouveaux documents, de même qu’elle ne se produit pas pour les suppressions, car elles sont idempotentes. |
409 | Un conflit de version a été détecté lors de la tentative d’indexation d’un document. | Oui | Cela peut se produire lorsque vous essayez d’indexer le même document plusieurs fois simultanément. |
422 | L’index est temporairement indisponible car il a été mis à jour avec l’indicateur « allowIndexDowntime » défini sur « true ». | Oui | |
503 | Votre service de recherche est temporairement indisponible, probablement en raison d’une charge importante. | Oui | Votre code doit attendre avant d’effectuer une nouvelle tentative, au risque de prolonger l’indisponibilité du service. |
Si votre code client génère fréquemment une réponse 207, l’une des raisons possibles est que le système est soumis à une charge élevée. Vous pouvez vous en assurer en vérifiant la propriété statusCode pour 503. Si statusCode est 503, nous vous recommandons de limiter les requêtes d’indexation. Sinon, si le trafic d'indexation ne diminue pas, le système peut commencer à rejeter toutes les requêtes avec des erreurs 503.
Le code d’état 429 indique que vous avez dépassé votre quota du nombre de documents par index. Vous devez créer un autre index ou effectuer une mise à niveau pour bénéficier de limites de capacité supérieures.
Remarque
Lorsque vous chargez des valeurs DateTimeOffset
avec des informations de fuseau horaire dans votre index, Recherche Azure AI normalise ces valeurs au format UTC. Par exemple, 2024-01-13T14:03:00-08:00 est stocké en tant que 2024-01-13T22:03:00Z. Si vous devez stocker des informations de fuseau horaire, ajoutez une colonne supplémentaire à votre index pour ce point de données.
Conseils pour l’indexation incrémentielle
Indexeurs automatisent l’indexation incrémentielle. Si vous pouvez utiliser un indexeur et si la source de données prend en charge le suivi des modifications, vous pouvez exécuter l’indexeur selon une planification périodique pour ajouter, mettre à jour ou remplacer du contenu pouvant faire l’objet d’une recherche afin qu’il soit synchronisé avec vos données externes.
Si vous effectuez directement des appels d’index via l’API push, utilisez
mergeOrUpload
comme action de recherche.La charge utile doit inclure les clés ou les identificateurs de chaque document que vous souhaitez ajouter, mettre à jour ou supprimer.
Si votre index comprend des champs vectoriels et que vous attribuez la valeur false à la propriété
stored
, assurez-vous de fournir le vecteur dans votre mise à jour partielle du document, même si la valeur est inchangée. Un effet secondaire de la définition destored
sur false est que les vecteurs sont supprimés sur une opération de réindexation. Vous pouvez éviter cela en fournissant le vecteur dans la charge utile du document.Pour mettre à jour le contenu des champs simples et des sous-champs dans des types complexes, répertoriez uniquement les champs que vous souhaitez modifier. Par exemple, si vous devez uniquement mettre à jour un champ de description, la charge utile doit être constituée de la clé de document et de la description modifiée. L’omission d’autres champs conserve leurs valeurs existantes.
Pour fusionner les modifications inline dans la collection de chaînes de caractères, indiquez la valeur complète. Rappelez-vous l’exemple de champ
tags
de la section précédente. Les nouvelles valeurs remplacent les anciennes pour un champ entier et il n’y a aucune fusion dans le contenu d’un champ.
Voici un exemple d’API REST illustrant ces conseils :
### Get Stay-Kay City Hotel by ID
GET {{baseUrl}}/indexes/hotels-vector-quickstart/docs('1')?api-version=2024-07-01 HTTP/1.1
Content-Type: application/json
api-key: {{apiKey}}
### Change the description, city, and tags for Stay-Kay City Hotel
POST {{baseUrl}}/indexes/hotels-vector-quickstart/docs/search.index?api-version=2024-07-01 HTTP/1.1
Content-Type: application/json
api-key: {{apiKey}}
{
"value": [
{
"@search.action": "mergeOrUpload",
"HotelId": "1",
"Description": "I'm overwriting the description for Stay-Kay City Hotel.",
"Tags": ["my old item", "my new item"],
"Address": {
"City": "Gotham City"
}
}
]
}
### Retrieve the same document, confirm the overwrites and retention of all other values
GET {{baseUrl}}/indexes/hotels-vector-quickstart/docs('1')?api-version=2024-07-01 HTTP/1.1
Content-Type: application/json
api-key: {{apiKey}}
Mettre à jour un schéma d’index
Le schéma d’index définit les structures de données physiques créées sur le service de recherche. Il n’existe donc pas de nombreuses modifications de schéma que vous pouvez apporter sans entraîner de reconstruction complète.
Mises à jour sans reconstruction
La liste suivante énumère les modifications de schéma qui peuvent être introduites en toute transparence dans un index existant. En règle générale, la liste inclut de nouveaux champs et fonctionnalités utilisés lors de l’exécution de la requête.
- Ajouter un nouveau champ
- Définir l’attribut
retrievable
sur un champ existant - Mettre à jour
searchAnalyzer
sur un champ ayant unindexAnalyzer
existant - Ajouter une nouvelle définition d’analyseur dans un index (qui peut être appliqué aux nouveaux champs)
- Ajouter, mettre à jour ou supprimer des profils de scoring
- Ajouter, mettre à jour ou supprimer des synonymMaps
- Ajouter, mettre à jour ou supprimer des configurations sémantiques
- Ajouter, mettre à jour ou supprimer des paramètres CORS
L’ordre des opérations est le suivant :
Modifiez le schéma avec les mises à jour de la liste précédente.
Mettre à jour le schéma d’index sur le service de recherche.
Mettre à jour le contenu de l’index pour correspondre à votre schéma révisé si vous avez ajouté un nouveau champ. Pour toutes les autres modifications, le contenu indexé existant est utilisé tel quel.
Lorsque vous mettez à jour un schéma d’index pour y inclure un nouveau champ, les documents existants dans l’index reçoivent une valeur Null pour ce champ. Lors de la prochaine tâche d’indexation, les valeurs des données sources externes remplacent les valeurs Null ajoutées par la Recherche Azure AI.
Il ne devrait pas y avoir d’interruption des requêtes au cours des mises à jour, mais les résultats des requêtes peuvent varier à mesure que les mises à jour sont appliquées.
Mises à jour nécessitant une reconstruction
Certaines modifications nécessitent une suppression et une reconstruction de l’index, en remplaçant l’index actuel par un nouveau.
Action | Description |
---|---|
Supprimer un champ | Pour supprimer physiquement toutes les traces d’un champ, vous devez regénerer l’index. Quand une reconstruction immédiate n’est pas pratique, vous pouvez modifier le code de l’application pour rediriger l’accès hors d’un champ obsolète ou utiliser les paramètres de requête searchFields et select pour choisir les champs à rechercher et à retourner. Physiquement, le contenu et la définition du champ restent dans l’index jusqu’à la régénération suivante, lors de laquelle est appliqué un schéma omettant le champ en question. |
Modifier une définition de champ | Les révisions apportées à un nom de champ, à un type de données ou à des attributs d’index spécifiques (searchable, filterable, sortable, facetable) exigent une reconstruction complète. |
Affecter un analyseur à un champ | Des analyseurs sont définis dans un index, affectés aux champs, puis appelés pendant l’indexation pour indiquer le mode de création des jetons. Vous pouvez à tout moment ajouter une nouvelle définition d’analyseur à un index, mais il n’est possible d’affecter l’analyseur qu’à la création du champ. Cette condition s’applique à la fois à la propriété analyzer et à la propriété indexAnalyzer. La propriété searchAnalyzer fait figure d’exception (elle peut être affectée à un champ existant). |
Mettre à jour ou supprimer une définition d’analyseur dans un index | Vous ne pouvez pas supprimer ou changer une configuration d’analyseur existante (analyseur, générateur de jetons, filtre de jetons ou filtre de caractères) dans l’index, à moins de regénérer la totalité de l’index. |
Ajouter un champ à un suggesteur | Si un champ existe déjà et que vous souhaitez l’ajouter à une construction Suggesters, reconstruisez l’index. |
Changer de niveau | Les mises à niveau sur place ne sont pas prises en charge. Si vous avez besoin de plus de capacité, créez un service et reconstruisez vos index à partir de zéro. Pour faciliter l’automatisation de ce processus, vous pouvez utiliser l’exemple de code index-backup-restore dans ce dépôt d’exemples .NET de Recherche Azure AI. Cette application sauvegarde votre index dans une série de fichiers JSON, puis recrée l’index dans un service de recherche que vous spécifiez. |
L’ordre des opérations est le suivant :
Obtenez une définition d’index pour vous y référer ultérieurement ou pour l’utiliser comme base d’une nouvelle version.
Envisagez d’utiliser une solution de sauvegarde et de restauration pour conserver une copie du contenu d’index. Il existe des solutions dans C# et dans Python. Nous vous recommandons la version de Python, car elle est plus à jour.
Si vous disposez d’une capacité sur votre service de recherche, conservez l’index existant pendant que vous créez et testez le nouvel index.
Supprimez l’index existant. Les requêtes ciblant l’index sont immédiatement supprimées. Souvenez-vous que la suppression d’un index est irréversible, détruisant le stockage physique pour la collection de champs et d’autres constructions.
Publier un index révisé, où le corps de la requête inclut des définitions et des configurations de champ modifiées ou modifiées.
Chargez l’index avec des documents d’une source externe. Les documents sont indexés à l’aide des définitions de champs et des configurations du nouveau schéma.
Lorsque vous créez l’index, le stockage physique est alloué pour chaque champ du schéma d’index, avec un index inversé créé pour chaque champ pouvant faire l’objet d’une recherche et un index vectoriel créé pour chaque champ vectoriel. Les champs non interrogeables peuvent être utilisés dans des filtres ou des expressions, mais ils n’ont pas d’index inversé et n’autorisent pas la recherche approximative ou en texte intégral. Sur une reconstruction d’index, ces index inversés et les index vectoriels sont supprimés et recréés en fonction du schéma d’index que vous fournissez.
Pour réduire la perturbation du code d’application, vous pouvez créer un alias d’index. Le code d’application référence l’alias, mais vous pouvez mettre à jour le nom de l’index vers lequel pointe l’alias.
Équilibrage des charges de travail
L’indexation ne s’exécute pas en arrière-plan, mais le service de recherche équilibre les travaux d’indexation par rapport aux requêtes en cours. Pendant l’indexation, vous pouvez surveiller les demandes de requête dans le portail Azure pour vous assurer que les requêtes sont traitées en temps voulu.
Si les charges de travail d’indexation introduisent des niveaux de latence de requête inacceptables, effectuez une analyse des performances et passez en revue ces conseils sur les performances pour tenter d’atténuer le problème.
Rechercher les mises à jour
Vous pouvez commencer à interroger un index dès que le premier document est chargé. Si vous connaissez l’ID d’un document, l’API REST de recherche de document retourne le document spécifique. Pour un test plus large, attendez que l’index soit entièrement chargé, puis utilisez des requêtes pour vérifier le contexte que vous vous attendez à voir.
Vous pouvez utiliser l’Explorateur de recherche ou un client REST pour rechercher du contenu mis à jour.
Si vous avez ajouté ou renommé un champ, utilisez select pour retourner ce champ :
"search": "*",
"select": "document-id, my-new-field, some-old-field",
"count": true
Le portail Azure fournit la taille de l’index et la taille de l’index vectoriel. Vous pouvez vérifier ces valeurs après la mise à jour d’un index, mais n’oubliez pas d’attendre un petit délai lorsque le service traite la modification et de tenir compte des taux d’actualisation du portail, ce qui peut être quelques minutes.
Supprimer les documents orphelins
La Recherche Azure AI prend en charge les opérations au niveau des documents, ce qui vous permet de rechercher, mettre à jour et supprimer un document spécifique de manière isolée. L’exemple suivant montre comment supprimer un document.
La suppression d’un document ne libère pas immédiatement de l’espace dans l’index. Toutes les quelques minutes, un processus en arrière-plan effectue la suppression physique. Que vous utilisiez le portail Azure ou une API pour retourner des statistiques d’index, vous pouvez vous attendre à un petit délai avant que la suppression ne soit reflétée dans les métriques du portail Azure et de l’API.
Identifiez le champ qui correspond à la clé de document. Dans le portail Azure, vous pouvez voir les champs de chaque index. Les clés de document sont des champs de chaîne dénotés par une icône de clé qui permet de les repérer plus facilement.
Vérifiez les valeurs du champ de clé du document :
search=*&$select=HotelId
. Une chaîne simple ne pose pas de difficultés, mais si l’index utilise un champ encodé en base 64 ou que les documents de recherche ont été générés à partir d’un paramètreparsingMode
, vous pouvez avoir affaire à des valeurs qui ne vous sont pas familières.Recherchez le document pour vérifier la valeur de l’ID du document et examiner son contenu avant de le supprimer. Spécifiez la clé ou l’ID du document dans la demande. Les exemples suivants illustrent une chaîne simple pour l’exemple d’index d’hôtels et une chaîne codée en base 64 pour la clé metadata_storage_path de l’index cog-search-demo.
GET https://[service name].search.windows.net/indexes/hotel-sample-index/docs/1111?api-version=2024-07-01
GET https://[service name].search.windows.net/indexes/cog-search-demo/docs/aHR0cHM6Ly9oZWlkaWJsb2JzdG9yYWdlMi5ibG9iLmNvcmUud2luZG93cy5uZXQvY29nLXNlYXJjaC1kZW1vL2d1dGhyaWUuanBn0?api-version=2024-07-01
Supprimer le document à l’aide d’une suppression de
@search.action
pour le supprimer de l’index de recherche.POST https://[service name].search.windows.net/indexes/hotels-sample-index/docs/index?api-version=2024-07-01 Content-Type: application/json api-key: [admin key] { "value": [ { "@search.action": "delete", "id": "1111" } ] }