Condividi tramite


Aggiornare o ricompilare un indice in Azure AI Search

Questo articolo illustra come aggiornare un indice esistente in Azure AI Search con modifiche dello schema o modifiche al contenuto tramite l'indicizzazione incrementale. Vengono illustrate le circostanze in cui sono necessarie le ricompilazioni e vengono fornite raccomandazioni per attenuare gli effetti delle ricompilazioni sulle richieste di query in corso.

Durante lo sviluppo attivo, è comune eliminare e ricompilare gli indici quando si esegue l'iterazione sulla progettazione degli indici. La maggior parte degli sviluppatori lavora con un piccolo campione rappresentativo dei dati in modo da rendere più veloce la reindicizzazione.

Per le modifiche dello schema nelle applicazioni già in produzione, è consigliabile creare e testare un nuovo indice che viene eseguito affiancato a un indice esistente. Usare un alias di indice per scambiare il nuovo indice in modo da evitare di modificare il codice dell'applicazione.

Aggiornare il contenuto

L'indicizzazione incrementale e la sincronizzazione di un indice rispetto alle modifiche apportate ai dati di origine sono fondamentali per la maggior parte delle applicazioni di ricerca. Questa sezione illustra il flusso di lavoro per l'aggiornamento del contenuto dei campi in un indice di ricerca tramite l'API REST, ma gli SDK di Azure forniscono funzionalità equivalenti.

Il corpo della richiesta contiene uno o più documenti da indicizzare. I documenti vengono identificati da una chiave con distinzione tra maiuscole e minuscole univoche. Ogni documento è associato a un'azione: "upload", "delete", "merge" o "mergeOrUpload". Le richieste di caricamento devono includere i dati del documento sotto forma di coppie chiave/valore.

{  
  "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)  
        ...  
    },  
    ...  
  ]  
}
  • Usare prima di tutto le API per il caricamento di documenti, ad esempio Documents - Index (REST) o un'API equivalente negli SDK di Azure. Per altre informazioni sulle tecniche di indicizzazione, vedere Caricare documenti.

  • Per un aggiornamento di grandi dimensioni, l'invio in batch (fino a 1.000 documenti per batch o circa 16 MB per batch, a seconda del limite previsto) è consigliato e migliora significativamente le prestazioni di indicizzazione.

  • Impostare il @search.action parametro nell'API per determinare l'effetto sui documenti esistenti.

    Azione Effetto
    eliminare Rimuove l'intero documento dall'indice. Per rimuovere un singolo campo, usare invece Unisci, impostando il campo in questione su Null. I documenti e i campi eliminati non liberano immediatamente spazio nell'indice. Ogni pochi minuti, un processo in background esegue l'eliminazione fisica. Sia che si usi la portale di Azure o un'API per restituire statistiche sugli indici, è possibile prevedere un piccolo ritardo prima che l'eliminazione venga riflessa nella portale di Azure e tramite le API.
    merge Aggiorna il documento già esistente e omette il documento che non può essere trovato. Unisci sostituisce i valori esistenti. Per questo motivo, assicurarsi di verificare la presenza di campi della raccolta che contengono più valori, ad esempio campi di tipo Collection(Edm.String). Ad esempio, se un campo tags inizia con un valore di ["budget"] e si esegue Unisci con ["economy", "pool"], il valore finale del campo tags sarà ["economy", "pool"]. Non sarà ["budget", "economy", "pool"].

    Lo stesso comportamento si applica alle raccolte complesse. Se il documento contiene un campo di raccolta complesso denominato Rooms con un valore [{ "Type": "Budget Room", "BaseRate": 75.0 }]e si esegue un merge con un valore pari [{ "Type": "Standard Room" }, { "Type": "Budget Room", "BaseRate": 60.5 }]a , il valore finale del campo Rooms sarà [{ "Type": "Standard Room" }, { "Type": "Budget Room", "BaseRate": 60.5 }]. Non aggiungerà o unisce valori nuovi ed esistenti.
    mergeOrUpload Si comporta come Unisci se il documento esiste già e Carica se il documento è nuovo. Questa è l'azione più comune per gli aggiornamenti incrementali.
    upload Simile a un "upsert" in cui il documento viene inserito se nuovo e aggiornato o sostituito se esistente. Se il documento non contiene valori richiesti dall'indice, il valore del campo del documento viene impostato su Null.

Le query continuano a essere eseguite durante l'indicizzazione, ma se si aggiornano o si rimuovono campi esistenti, è possibile prevedere risultati misti e un'incidenza più elevata della limitazione.

Nota

Non esistono garanzie di ordinamento per cui viene eseguita prima l'azione nel corpo della richiesta. Non è consigliabile avere più azioni di "merge" associate allo stesso documento in un singolo corpo della richiesta. Se sono necessarie più azioni di "merge" per lo stesso documento, eseguire l'unione lato client prima di aggiornare il documento nell'indice di ricerca.

Risposte

Il codice di stato 200 viene restituito per una risposta con esito positivo, ovvero tutti gli elementi sono stati archiviati in modo permanente e inizieranno a essere indicizzati. L'indicizzazione viene eseguita in background e rende disponibili nuovi documenti( ovvero queryable e ricercabili) pochi secondi dopo il completamento dell'operazione di indicizzazione. Il ritardo specifico dipende dal carico del servizio.

L'indicizzazione riuscita è indicata dalla proprietà status impostata su true per tutti gli elementi, nonché la statusCode proprietà impostata su 201 (per i documenti appena caricati) o 200 (per i documenti uniti o eliminati):

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

Il codice di stato 207 viene restituito quando almeno un elemento non è stato indicizzato correttamente. Gli elementi che non sono stati indicizzati hanno il campo di stato impostato su false. Le errorMessage proprietà e statusCode indicano il motivo dell'errore di indicizzazione:

{
  "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 errorMessage proprietà indica il motivo dell'errore di indicizzazione, se possibile.

La tabella seguente descrive i diversi codici di stato di ogni documento che possono essere restituiti nella risposta. Alcuni codici di stato indicano problemi con la richiesta stessa, mentre altri indicano condizioni di errore temporanee. Per queste ultime è necessario riprovare dopo un breve intervallo di tempo.

Codice di stato significato Non irreversibile Note
200 Il documento è stato modificato o eliminato correttamente. n/d Le operazioni di eliminazione sono idempotenti. Ovvero, anche se non esiste una chiave del documento nell'indice, il tentativo di un'operazione di eliminazione con tale chiave genera un codice di stato 200.
201 Il documento è stato creato correttamente. n/d
400 Si è verificato un errore nel documento che ne ha impedito l'indicizzazione. No Il messaggio di errore nella risposta indica l'errore del documento.
404 Impossibile unire il documento perché la chiave specificata non esiste nell'indice. No Questo errore non si verifica per i caricamenti perché creano nuovi documenti e non si verifica per le eliminazioni perché sono idempotenti.
409 È stato rilevato un conflitto di versione nel tentativo di indicizzare un documento. Ciò può verificarsi quando si prova a indicizzare lo stesso documento più di una volta contemporaneamente.
422 L'indice è temporaneamente non disponibile perché è stato aggiornato con il flag 'allowIndexDowntime' impostato su 'true'.
503 Il servizio di ricerca è temporaneamente non disponibile, probabilmente a causa di un sovraccarico. In questo caso, il codice deve attendere prima di riprovare o si rischia di prolungare la non disponibilità del servizio.

Se il codice client rileva spesso una risposta 207, un possibile motivo è che il sistema è sotto carico. Per confermarlo, controllare la proprietà statusCode per 503. Se statusCode è 503, è consigliabile limitare le richieste di indicizzazione. Se non si riduce il traffico di indicizzazione, è possibile che il sistema inizi a rifiutare tutte le richieste con errori 503.

Il codice di stato 429 indica che è stata superata la quota del numero di documenti per indice. È necessario creare un nuovo indice o effettuare l'aggiornamento per ottenere limiti di capacità più elevati.

Nota

Quando si caricano DateTimeOffset valori con informazioni sul fuso orario nell'indice, Ricerca di intelligenza artificiale di Azure normalizza questi valori in formato UTC. Ad esempio, 2024-01-13T14:03:00-08:00 viene archiviato come 2024-01-13T22:03:00Z. Se è necessario archiviare le informazioni sul fuso orario, aggiungere una colonna aggiuntiva all'indice per questo punto dati.

Suggerimenti per l'indicizzazione incrementale

  • Gli indicizzatori automatizzano l'indicizzazione incrementale. Se è possibile usare un indicizzatore e se l'origine dati supporta il rilevamento delle modifiche, è possibile eseguire l'indicizzatore in una pianificazione ricorrente per aggiungere, aggiornare o sovrascrivere il contenuto ricercabile in modo che venga sincronizzato con i dati esterni.

  • Se si effettuano chiamate di indice direttamente tramite l'API push, usare mergeOrUpload come azione di ricerca.

  • Il payload deve includere le chiavi o gli identificatori di ogni documento da aggiungere, aggiornare o eliminare.

  • Se l'indice include campi vettoriali e si imposta la proprietà stored su false, assicurarsi di fornire il vettore nell'aggiornamento parziale del documento, anche se il valore è invariato. Un effetto collaterale dell'impostazione di stored su false è che i vettori vengono rilasciati in un'operazione di reindicizzazione. Se si specifica il vettore nel payload dei documenti, si impedisce che ciò accada.

  • Per aggiornare il contenuto di campi semplici e sottocampi in tipi complessi, elencare solo i campi da modificare. Ad esempio, se è necessario aggiornare solo un campo descrizione, il payload deve essere costituito dalla chiave del documento e dalla descrizione modificata. L'omissione di altri campi mantiene i relativi valori esistenti.

  • Per unire le modifiche inline nella raccolta di stringhe, specificare l'intero valore. Richiamare l'esempio di campo tags dalla sezione precedente. I nuovi valori sovrascrivono i valori precedenti per un intero campo e non esiste un'unione all'interno del contenuto di un campo.

Di seguito è riportato un esempio di API REST che illustra questi suggerimenti:

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

Aggiornare uno schema di indice

Lo schema dell'indice definisce le strutture di dati fisiche create nel servizio di ricerca, in modo che non siano disponibili molte modifiche da apportare allo schema senza incorrere in una ricompilazione completa.

Aggiornamenti senza ricompilazione

Nell'elenco seguente vengono enumerate le modifiche dello schema che possono essere introdotte facilmente in un indice esistente. In genere, l'elenco include nuovi campi e funzionalità usati durante l'esecuzione della query.

  • Aggiungi un nuovo campo
  • Impostare l'attributo retrievable su un campo esistente
  • Aggiornare searchAnalyzer in un campo con un indexAnalyzeresistente
  • Aggiungere una nuova definizione dell'analizzatore in un indice (che può essere applicato ai nuovi campi)
  • Aggiungere, aggiornare o eliminare profili di punteggio
  • Aggiungere, aggiornare o eliminare synonymMaps
  • Aggiungere, aggiornare o eliminare configurazioni semantiche
  • Aggiungere, aggiornare o eliminare le impostazioni di CORS

L'ordine delle operazioni è:

  1. Ottenere la definizione dell'indice.

  2. Rivedere lo schema con gli aggiornamenti dell'elenco precedente.

  3. Aggiornare lo schema dell'indice nel servizio di ricerca.

  4. Aggiornare il contenuto dell'indice in modo che corrisponda allo schema modificato se è stato aggiunto un nuovo campo. Per tutte le altre modifiche, il contenuto indicizzato esistente viene usato così come è.

Quando si aggiorna uno schema di indice per includere un nuovo campo, ai documenti esistenti nell'indice viene assegnato un valore Null per tale campo. Nel processo di indicizzazione successivo, i valori dei dati di origine esterni sostituiscono i valori Null aggiunti da Azure AI Search.

Non dovrebbero verificarsi interruzioni di query durante gli aggiornamenti, ma i risultati delle query varieranno man mano che gli aggiornamenti avranno effetto.

Aggiornamenti che richiedono una ricompilazione

Alcune modifiche richiedono un'eliminazione e la ricompilazione dell'indice, sostituendo un indice corrente con uno nuovo.

Azione Descrizione
Eliminare un campo Per rimuovere fisicamente tutte le tracce di un campo è necessario ricompilare l'indice. Quando una ricompilazione immediata non è pratica, è possibile modificare il codice dell'applicazione per reindirizzare l'accesso da un campo obsoleto o usare searchFields e selezionare i parametri di query per scegliere quali campi vengono cercati e restituiti. Fisicamente la definizione del campo e i contenuti rimangono nell'indice fino alla successiva ricompilazione, quando si applica uno schema che omette il campo in questione.
Modificare la definizione di un campo Le revisioni di un nome di campo, di un tipo di dati o di attributi di indice specifici (ricercabili, filtrabili, ordinabili, con facet) richiedono una ricompilazione completa.
Assegnare un analizzatore a un campo Gli analizzatori vengono definiti in un indice, assegnati ai campi e quindi richiamati durante l'indicizzazione per informare su come vengono creati i token. È possibile aggiungere una nuova definizione di analizzatore a un indice in qualsiasi momento, ma è possibile assegnare un analizzatore solo quando il campo viene creato. Questo vale per entrambe le proprietà analyzer e indexAnalyzer. La proprietà searchAnalyzer è un'eccezione perché è possibile assegnare questa proprietà a un campo esistente.
Aggiornare o eliminare una definizione di analizzatore in un indice Non è possibile eliminare o modificare una configurazione dell'analizzatore esistente (analizzatore, tokenizer, filtro token o filtro char) nell'indice a meno che non si ricompili l'intero indice.
Aggiungere un campo a uno strumento suggerimenti Se esiste già un campo e si vuole aggiungerlo a un costrutto Componenti per il suggerimento e ricompilare l'indice.
Cambiare i livelli Gli aggiornamenti sul posto non sono supportati. Se è necessaria una maggiore capacità, creare un nuovo servizio e ricompilare gli indici da zero. Per automatizzare questo processo, è possibile usare il codice di esempio index-backup-restore in questo repository di esempio .NET di Azure AI Search. Questa app esegue il backup dell'indice in una serie di file JSON e quindi ricrea l'indice in un servizio di ricerca specificato.

L'ordine delle operazioni è:

  1. Ottenere una definizione di indice nel caso in cui sia necessaria per riferimento futuro o per usarla come base per una nuova versione.

  2. Prendere in considerazione l'uso di una soluzione di backup e ripristino per mantenere una copia del contenuto dell'indice. Sono disponibili soluzioni in C# e in Python. È consigliabile usare la versione di Python perché è più aggiornata.

    Se si ha la capacità nel servizio di ricerca, mantenere l'indice esistente durante la creazione e il test di quello nuovo.

  3. Eliminare l'indice esistente. Le query destinate all'indice vengono eliminate immediatamente. Tenere presente che l'eliminazione di un indice è irreversibile, eliminando l'archiviazione fisica per la raccolta di campi e altri costrutti.

  4. Pubblicare un indice modificato, in cui il corpo della richiesta include definizioni e configurazioni di campo cambiate o modificate.

  5. Caricare l'indice con i documenti da un'origine esterna. I documenti vengono indicizzati usando le definizioni dei campi e le configurazioni del nuovo schema.

Quando si crea l'indice, l'archiviazione fisica viene allocata per ogni campo nello schema dell'indice, con un indice invertito creato per ogni campo ricercabile e un indice vettoriale creato per ogni campo vettoriale. I campi non ricercabili possono essere usati nei filtri o nelle espressioni, ma non hanno indici invertiti e non supportano la ricerca full-text o fuzzy. In una ricompilazione dell'indice, questi indici invertiti e gli indici vettoriali vengono eliminati e ricreati in base allo schema di indice specificato.

Per ridurre al minimo l'interruzione del codice dell'applicazione, è consigliabile creare un alias di indice. Il codice dell'applicazione fa riferimento all'alias, ma è possibile aggiornare il nome dell'indice a cui punta l'alias.

Bilanciamento dei carichi di lavoro

L'indicizzazione non viene eseguita in background, ma il servizio di ricerca bilancerà tutti i processi di indicizzazione con le query in corso. Durante l'indicizzazione, è possibile monitorare le richieste di query nel portale di Azure per assicurarsi che le query vengano completate in modo tempestivo.

Se l'indicizzazione dei carichi di lavoro introduce livelli inaccettabili di latenza delle query, eseguire analisi delle prestazioni ed esaminare questi suggerimenti sulle prestazioni per una potenziale mitigazione.

Verifica della presenza di aggiornamenti

È possibile iniziare a eseguire query su un indice subito dopo il caricamento del primo documento. Se si conosce l'ID di un documento, l'API REST di ricerca documenti restituisce il documento specifico. Per un test su più larga scala, è possibile aspettare che l'indice venga caricato completamente e quindi usare le query per verificare il contesto che ci si aspetta di vedere.

È possibile usare Esplora ricerche o un Client REST per verificare la disponibilità di contenuti aggiornati.

Se è stato aggiunto o rinominato un campo, usare select per restituire il campo:

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

Il portale di Azure fornisce la dimensione dell'indice e la dimensione dell'indice vettoriale. È possibile controllare questi valori dopo l'aggiornamento di un indice, ma ricordarsi di aspettarsi un piccolo ritardo durante l'elaborazione della modifica e tenere conto delle frequenze di aggiornamento del portale, che possono essere di pochi minuti.

Eliminare documenti orfani

Azure AI Search supporta le operazioni a livello di documento in modo da poter cercare, aggiornare ed eliminare un documento specifico in isolamento. L'esempio seguente mostra come eliminare un documento.

L'eliminazione di un documento non libera immediatamente spazio nell'indice. Ogni pochi minuti, un processo in background esegue l'eliminazione fisica. Sia che si usi la portale di Azure o un'API per restituire statistiche sugli indici, è possibile prevedere un piccolo ritardo prima che l'eliminazione venga riflessa nelle metriche portale di Azure e API.

  1. Identificare quale campo è la chiave del documento. Nella portale di Azure è possibile visualizzare i campi di ogni indice. Le chiavi del documento sono campi stringa e sono contrassegnate con un'icona a forma di chiave per renderle più facili da individuare.

  2. Controllare i valori del campo chiave del documento: search=*&$select=HotelId. Una stringa semplice è lineare, ma se l'indice usa un campo con codifica base 64 o se i documenti di ricerca sono stati generati da un'impostazione di parsingMode, è possibile usare valori con cui non si ha familiarità.

  3. Cerca il documento per verificare il valore dell'ID documento e per esaminarne il contenuto prima di eliminarlo. Specificare la chiave o l'ID documento nella richiesta. Negli esempi seguenti viene illustrata una stringa semplice per l'indice di esempio Hotel e una stringa con codifica base 64 per la chiave metadata_storage_path dell'indice 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. Eliminare il documento usando un @search.action di eliminazione per rimuoverlo dall'indice di ricerca.

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

Vedi anche