Compartir vía


Actualización o recompilación de un índice en Búsqueda de Azure AI

En este artículo se explica cómo actualizar un índice existente en Búsqueda de Azure AI con cambios de esquema o cambios de contenido a través de la indexación incremental. En él se explican las circunstancias en las que se requieren recompilaciones y se dan recomendaciones para mitigar el efecto de las recompilaciones en las solicitudes de consulta en curso.

Durante el desarrollo activo, es habitual quitar y volver a generar índices al iterar sobre el diseño de índices. La mayoría de los desarrolladores trabajan con una pequeña muestra representativa de sus datos para que la reindexación sea más rápida.

En el caso de cambios de esquema en las aplicaciones ya en producción, se recomienda crear y probar un nuevo índice que se ejecute en paralelo a un índice existente. Use un alias de índice para intercambiar en el nuevo índice para que pueda evitar cambios en el código de la aplicación.

Actualización del contenido

En la mayoría de las aplicaciones de búsqueda, es fundamental la indexación incremental y la sincronización de un índice con los cambios en los datos de origen. En esta sección se explica el flujo de trabajo para actualizar el contenido del campo en un índice de búsqueda a través de la API de REST, pero los SDK de Azure proporcionan una funcionalidad equivalente.

El cuerpo de la solicitud contiene uno o más documentos para indexar. Los documentos se identifican mediante una clave única que distingue mayúsculas de minúsculas. Cada documento está asociado a una acción: "upload", "delete", "merge" o "mergeOrUpload". Las solicitudes de carga deben incluir los datos del documento como un conjunto de pares de clave/valor.

{  
  "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)  
        ...  
    },  
    ...  
  ]  
}
  • En primer lugar, use las API para cargar documentos, como Documentos - Índice (REST) o una API equivalente en los SDK de Azure. Para más información sobre las técnicas de indexación, consulte Carga de documentos.

  • Para una actualización grande, se recomienda el procesamiento por lotes (hasta 1000 documentos por lote, o aproximadamente 16 MB por lote, lo que ocurra primero) y mejora significativamente el rendimiento de la indexación.

  • Establezca el parámetro @search.action en la API para determinar el efecto en los documentos existentes.

    Action Efecto
    delete Elimina todo el documento del índice. Si solo quiere quitar un campo individual, utilice merge en su lugar, estableciendo el campo en cuestión en NULL. Los documentos y campos eliminados no liberan espacio inmediatamente en el índice. Cada pocos minutos, un proceso en segundo plano realiza la eliminación física. Tanto si usa Azure Portal como una API para devolver estadísticas de índice, puede esperar un pequeño retraso antes de que la eliminación se refleje en Azure Portal y a través de las API.
    merge Actualiza un documento que ya existe y produce un error en un documento si no se encuentra. La operación "merge" reemplaza los valores existentes. Por esta razón, asegúrese de comprobar que los campos de colección contengan varios valores, como los campos de tipo Collection(Edm.String). Por ejemplo, si el campo tags empieza con un valor de ["budget"] y ejecuta una operación "merge" con el valor ["economy", "pool"], el valor final del campo tags será ["economy", "pool"]. No será ["budget", "economy", "pool"].

    El mismo comportamiento se aplica a colecciones complejas. Si el documento contiene un campo de colección complejo denominado Salas con un valor de [{ "Type": "Budget Room", "BaseRate": 75.0 }] y ejecuta una combinación con un valor de [{ "Type": "Standard Room" }, { "Type": "Budget Room", "BaseRate": 60.5 }], el valor final del campo Salas será [{ "Type": "Standard Room" }, { "Type": "Budget Room", "BaseRate": 60.5 }]. No anexará ni combinará valores nuevos y existentes.
    mergeOrUpload Se comporta como merge si el documento existe, y como upload si el documento es nuevo. Esta es la acción más común para las actualizaciones incrementales.
    upload Similar a una operación "upsert", donde se inserta el documento si es nuevo, y se actualiza o reemplaza si ya existe. Si al documento le faltan valores que requiere el índice, el valor del campo de documento se establece en NULL.

Las consultas continúan ejecutándose durante la indexación, pero si va a actualizar o quitar campos existentes, puede esperar resultados mixtos y una mayor incidencia de limitación.

Nota:

No hay garantías de ordenación para las que se ejecuta primero la acción en el cuerpo de la solicitud. No se recomienda tener varias acciones de "combinación" asociadas al mismo documento en un único cuerpo de solicitud. Si hay varias acciones de "combinación" necesarias para el mismo documento, realice la combinación del lado cliente antes de actualizar el documento en el índice de búsqueda.

Respuestas

El código de estado 200 se devuelve para una respuesta correcta, lo que significa que todos los elementos se han almacenado de forma duradera y empezarán a indexarse. La indexación se ejecuta en segundo plano y hace que los nuevos documentos estén disponibles (es decir, consultables y buscables) unos segundos después de que se complete la operación de indexación. El retraso específico depende de la carga del servicio.

La indexación correcta se indica mediante la propiedad status que se establece en true para todos los elementos, así como la propiedad statusCode que se establece en 201 (para documentos recién cargados) o 200 (para documentos combinados o eliminados):

{
  "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
    }
  ]
}

El código de estado 207 se devuelve cuando al menos un elemento no se indizara correctamente. Los elementos que no se han indexado tienen el campo de estado establecido en false. Las propiedades errorMessage y statusCode indican el motivo del error de indexación:

{
  "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 propiedad errorMessage indica el motivo del error de indexación si es posible.

La tabla siguiente explica los distintos códigos de estado por documento que se pueden devolver en la respuesta. Algunos códigos de estado indican problemas con la propia solicitud, mientras que otros indican condiciones de error temporales. En este último caso debe volver a intentarlo después de un tiempo.

status code Significado Se puede volver a intentar Notas
200 Documento correctamente modificado o eliminado. N/D Las operaciones de eliminación son idempotentes. Es decir, aunque no exista una clave de documento en el índice, al intentar una operación de eliminación con esa clave se producirá un código de estado 200.
201 El documento se creó correctamente. N/D
400 Se produjo un error en el documento que ha impedido que se indexe. No El mensaje de error de la respuesta indica lo que está mal con el documento.
404 No se pudo combinar el documento porque la clave especificada no existe en el índice. No Este error no se produce para las cargas, ya que crean nuevos documentos y no se produce para las eliminaciones porque son idempotentes.
409 Se detectó un conflicto de versión al intentar indexar un documento. Esto puede ocurrir si intenta indexar el mismo documento más de una vez al mismo tiempo.
422 El índice no está disponible temporalmente porque se ha actualizado con el indicador 'allowIndexDowntime' establecido en 'true'.
503 El servicio de búsqueda no está disponible temporalmente, posiblemente debido a una carga elevada. En este caso, el código debe esperar antes de reintentar ya que, de lo contrario, se arriesga a prolongar la no disponibilidad del servicio.

Si el código de cliente encuentra con frecuencia una respuesta 207, una posible razón es que el sistema está bajo carga. Para confirmarlo, compruebe la propiedad de statusCode para 503. Si statusCode es 503, se recomienda limitar las solicitudes de indexación. De lo contrario, si el tráfico de indexación de tráfico no se reduce, es posible que el sistema comience a rechazar todas las solicitudes mediante errores 503.

El código de estado 429 indica que se ha superado la cuota del número de documentos por índice. Debe crear un nuevo índice o actualizar para obtener límites de capacidad superiores.

Nota:

Al cargar valores de DateTimeOffset con información de zona horaria en el índice, Azure AI Search normaliza estos valores a UTC. Por ejemplo, 2024-01-13T14:03:00-08:00 se almacena como 2024-01-13T22:03:00Z. Si necesita almacenar información de zona horaria, agregue una columna adicional al índice para este punto de datos.

Sugerencias para la indexación incremental

  • Los indexadores automatizan la indexación incremental. Si puede usar un indexador y, si el origen de datos admite el seguimiento de cambios, puede ejecutar el indexador según una programación periódica para agregar, actualizar o sobrescribir contenido que se puede buscar para que se sincronice con los datos externos.

  • Si realiza llamadas de índice directamente a través de la API de inserción, use mergeOrUpload como acción de búsqueda.

  • La carga debe incluir las claves o identificadores de todos los documentos que desea agregar, actualizar o eliminar.

  • Si el índice incluye campos vectoriales y establece la propiedad stored en false, asegúrese de proporcionar el vector en la actualización parcial del documento, incluso si el valor no cambia. Un efecto secundario de establecer stored en false es que los vectores se quitan en una operación de reindexación. Proporcionar el vector en la carga de documentos impide que esto suceda.

  • Para actualizar el contenido de campos simples y subcampos de tipos complejos, enumere solo los campos que desea cambiar. Por ejemplo, si solo necesita actualizar un campo de descripción, la carga debe constar de la clave del documento y la descripción modificada. Si se omiten otros campos, se conservan sus valores existentes.

  • Para combinar los cambios insertados en la colección de cadenas, proporciona todo el valor. Recuerde el ejemplo del campo tags de la sección anterior. Los nuevos valores sobrescriben los valores antiguos para un campo completo y no hay ninguna combinación en el contenido de un campo.

Este es un ejemplo de API de REST que muestra estas sugerencias:

### 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}}

Actualizar un esquema de índice

El esquema de índice define las estructuras de datos físicas creadas en el servicio de búsqueda, por lo que no hay muchos cambios de esquema que pueda realizar sin incurrir en una recompilación completa.

Actualizaciones sin recompilación

En la lista siguiente se enumeran los cambios de esquema que se pueden introducir fácilmente en un índice existente. Por lo general, la lista incluye nuevos campos y funcionalidades que se usan durante la ejecución de la consulta.

  • Agregar un campo nuevo
  • Establecer el atributo retrievable en un campo existente
  • Actualizar searchAnalyzer en un campo que tiene un elemento indexAnalyzer ya existente
  • Agregue una nueva definición del analizador en un índice (que se puede aplicar a nuevos campos)
  • Agregar, actualizar o eliminar perfiles de puntuación
  • Agregar, actualizar o eliminar synonymMaps
  • Agregar, actualizar o eliminar configuraciones semánticas
  • Adición, actualización o eliminación de configuraciones CORS

El orden de las operaciones es:

  1. Obtener la definición del índice.

  2. Revisar el esquema con actualizaciones de la lista anterior.

  3. Actualizar el esquema de índice en el servicio de búsqueda.

  4. Actualizar el contenido del índice para que coincida con el esquema revisado si ha agregado un nuevo campo. Para todos los demás cambios, el contenido indexado existente se usa tal cual.

Al actualizar un esquema de índice, para incluir un nuevo campo, los documentos existentes en el índice reciben un valor null para ese campo. En el siguiente trabajo de indexación, los valores de los datos de origen externo reemplazan los valores null agregados por Búsqueda de Azure AI.

No debe haber interrupciones en las consultas durante las actualizaciones, pero los resultados de las consultas variarán a medida que se apliquen las actualizaciones.

Actualizaciones que requieren una recompilación

Algunas modificaciones requieren una eliminación y recompilación de índices, reemplazando un índice actual por uno nuevo.

Acción Descripción
Eliminar un campo Para quitar físicamente todos los rastros de un campo, tendrá que recompilar el índice. Cuando una recompilación inmediata no es práctica, puede modificar el código de la aplicación para redirigir el acceso fuera de un campo obsoleto o usar los parámetros de consulta searchFields y select para elegir qué campos se buscan y devuelven. Físicamente, el contenido y la definición del campo permanecen en el índice hasta la próxima recompilación, cuando aplica un esquema que omite el campo en cuestión.
Cambiar la definición de un campo Las revisiones del nombre, el tipo de datos o los atributos de índice específicos (si se pueden buscar, filtrar, ordenar, clasificar) de un campo requiere una recompilación completa.
Asignar un analizador a un campo Los analizadores se definen en un índice, se asignan a campos y, a continuación, se invocan durante la indexación para informar sobre cómo se crean los tokens. Puede agregar una nueva definición de analizador a un índice en cualquier momento, pero solo puede asignar un analizador cuando se crea el campo. Esto es así tanto para la propiedad analyzer como para la propiedad indexAnalyzer. La propiedad searchAnalyzer es una excepción (puede asignar esta propiedad a un campo existente).
Actualizar o eliminar una definición de analizador en un índice No puede eliminar ni cambiar una configuración de analizador existente (analizador, tokenizador, filtro de token o filtro de caracteres) en el índice, a menos que recompile todo el índice.
Agregar un campo a un proveedor de sugerencias Si ya existe un campo y desea agregarlo a una construcción de proveedor de sugerencias, recompile el índice.
Cambiar los niveles No se admiten las actualizaciones locales. Si necesita más capacidad, cree otro servicio y recompilar los índices desde cero. Para ayudar a automatizar este proceso, puede usar el código de ejemplo index-backup-restore de este repositorio de ejemplo .NET de Azure AI Search. Esta aplicación hace una copia de seguridad del índice en una serie de archivos JSON y luego vuelve a crear el índice en un servicio de búsqueda que especifique.

El orden de las operaciones es:

  1. Obtén una definición de índice, por si la necesitas para futuras referencias o para usarla como base para una versión nueva.

  2. Considere la posibilidad de usar una solución de copia de seguridad y restauración para conservar una copia del contenido del índice. Hay soluciones en C# y en Python. Se recomienda la versión de Python porque está más actualizada.

    Si tienes capacidad en el servicio de búsqueda, mantén el índice existente al crear y probar el nuevo.

  3. Eliminar el índice existente. Se eliminan inmediatamente todas las consultas dirigidas a ese índice. Recuerde que la eliminación de un índice es una acción irreversible, ya que se destruye el almacenamiento físico para la colección de campos y otras construcciones.

  4. Publique un índice revisado, en el que el cuerpo de la solicitud incluya definiciones y configuraciones de campos modificadas o cambiadas.

  5. Cargue documentos en el índice desde un origen de datos externo. Los documentos se indexan mediante las definiciones y configuraciones de campos del nuevo esquema.

Cuando se crea el índice, se asigna almacenamiento físico para cada campo del esquema de índice; se crea además un índice invertido para cada campo de búsqueda y un índice vectorial para cada campo vectorial. Los campos que no pueden buscarse se pueden usar en filtros o expresiones, pero no cuentan con índices invertidos y no están habilitados para búsquedas de texto completo o aproximadas. En una recompilación de índices, estos índices invertidos se eliminan y vuelven a crear en función del esquema de índice proporcionado.

Para minimizar la interrupción del código de la aplicación, considere la posibilidad de crear un alias de índice. El código de aplicación hace referencia al alias, pero puede actualizar el nombre del índice al que apunta el alias.

Equilibrio de cargas de trabajo

La indexación no se ejecuta en segundo plano, pero el servicio de búsqueda equilibrará los trabajos de indexación con las consultas en curso. Durante la indexación, puede supervisar las solicitudes de consulta en Azure Portal para asegurarse de que las consultas se completan de forma oportuna.

Si las cargas de trabajo de indexación presentan unos niveles inaceptables de latencia de consulta, realice un análisis de rendimiento y revise estas sugerencias de rendimiento para una posible mitigación.

Buscar actualizaciones

Puede empezar a consultar un índice en cuanto se carga el primer documento. Si conoce el identificador de un documento, la API REST para buscar documentos devuelve el documento específico. Para realizar pruebas más amplias, debe esperar hasta que el índice se haya cargado completamente y, a continuación, usar consultas para comprobar el contexto que espera ver.

Puede usar el explorador de búsqueda o un cliente REST para comprobar el contenido actualizado.

Si ha agregado o cambiado el nombre de un campo, use seleccionar para devolver ese campo:

"search": "*",
"select": "document-id, my-new-field, some-old-field",
"count": true

Azure Portal proporciona el tamaño del índice y el tamaño del índice vectorial. Puede comprobar estos valores después de actualizar un índice, pero recuerde que cabe esperar un pequeño retraso a medida que el servicio procesa el cambio y que debe tener en cuenta las velocidades de actualización del portal, que puede ser de unos minutos.

Eliminación de documentos huérfanos

Azure AI Search admite operaciones de nivel de documento para que pueda buscar, actualizar y eliminar un documento concreto de forma aislada. En el ejemplo siguiente se muestra cómo eliminar un documento.

La eliminación de un documento no libera inmediatamente espacio en el índice. Cada pocos minutos, un proceso en segundo plano realiza la eliminación física. Tanto si usa Azure Portal como una API para devolver estadísticas de índice, puede esperar un pequeño retraso antes de que la eliminación se refleje en Azure Portal y las métricas de API.

  1. Identifique qué campo es la clave del documento. En Azure Portal, puede ver los campos de cada índice. Las claves del documento son campos de cadena y se indican con un icono de una llave, con el fin de que sean más fáciles de detectar.

  2. Compruebe los valores del campo de clave del documento: search=*&$select=HotelId. Una cadena simple es sencilla, pero si el índice usa un campo codificado en base 64 o si se generaron documentos de búsqueda a partir de una configuración parsingMode, es posible que esté trabajando con valores con los que no está familiarizado.

  3. Consulte el documento para comprobar el valor del identificador del documento y examinar su contenido antes de eliminarlo. Especifique la clave o el identificador de documento en la solicitud. En los ejemplos siguientes se muestra una cadena sencilla del índice de ejemplo Hotels y una cadena codificada en base 64 para la clave metadata_storage_path del índice 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
    
  4. Elimine el documento mediante una eliminación @search.action para quitarlo del índice de búsqueda.

    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"  
        }  
      ]  
    }
    

Consulte también