Indicizzare BLOB e file Markdown in Azure AI Search

Nota

Azure AI Search è disponibile tramite il portale di Azure, le API REST e Azure SDK. È inoltre alla base di Foundry IQ, il livello di conoscenza gestito che trasforma il contenuto aziendale in knowledge base riutilizzabili e con riconoscimento delle autorizzazioni per gli agenti nel portale di Microsoft Foundry.

Importante

Queste funzionalità e caratteristiche supportano la connessione ad altri servizi Microsoft e a servizi di terze parti. L'utilizzo di questi servizi è soggetto alle rispettive condizioni e potrebbe comportare l'elaborazione o l'archiviazione dei dati al di fuori del limite di conformità Azure, nonché il flusso dei dati nel limite di conformità Azure.

È tua responsabilità gestire l'eventuale trasferimento dei tuoi dati al di fuori dei confini di conformità e geografici della tua organizzazione e le relative implicazioni, nonché garantire che siano predisposte le autorizzazioni, i limiti e le approvazioni appropriati.

L'utente è responsabile di esaminare e testare attentamente le applicazioni compilate nel contesto dei casi d'uso specifici e di prendere tutte le decisioni e le personalizzazioni appropriate. Ciò include l'implementazione di mitigazioni di intelligenza artificiale responsabili, ad esempio metaprompt, filtri di contenuto o altri sistemi di sicurezza, e garantire che le applicazioni soddisfino gli standard di qualità, affidabilità, sicurezza e attendibilità appropriati. Per altre informazioni, vedere la nota sulla trasparenza Azure AI Search.

In Azure AI Search, gli indicizzatori per Archiviazione BLOB di Azure, File di Azure e Microsoft OneLake supportano una modalità di analisi markdown per i file Markdown. I file Markdown possono essere indicizzati in due modi:

  • Modalità di analisi uno-a-molti, che crea più documenti di ricerca per ogni file Markdown.
  • Modalità di analisi uno-a-uno, che crea un documento di ricerca per ogni file Markdown.

Suggerimento

Dopo aver esaminato questo articolo, continuare a Tutorial: Cerca dati Markdown da Archiviazione BLOB di Azure.

Prerequisiti

  • Un'origine dati supportata: Archiviazione BLOB di Azure, archiviazione file Azure, Microsoft OneLake.

    Per OneLake, assicurarsi di soddisfare tutti i requisiti dell'indicizzatore OneLake.

    Archiviazione di Azure per gli indicizzatori blob e gli indicizzatori di file (anteprima) è un account di archiviazione con prestazioni standard (per utilizzo generico v2) che supporta i livelli di accesso frequente e sporadico.

Parametri della modalità di analisi Markdown

I parametri della modalità di analisi vengono specificati in una definizione dell'indicizzatore quando si crea o si aggiorna un indicizzatore.

POST https://[service name].search.windows.net/indexers?api-version=2026-04-01
Content-Type: application/json
api-key: [admin key]

{
  "name": "my-markdown-indexer",
  "dataSourceName": "my-blob-datasource",
  "targetIndexName": "my-target-index",
  "parameters": {
    "configuration": {
      "parsingMode": "markdown",
      "markdownParsingSubmode": "oneToMany",
      "markdownHeaderDepth": "h6"
    }
  },
}

L'indicizzatore BLOB fornisce un submode parametro per determinare la struttura di output dei documenti di ricerca. La modalità di analisi Markdown offre le opzioni di sottomode seguenti:

modalità di analisi sintattica sottomodalità Cerca documento Descrizione
markdown oneToMany Più documenti per BLOB (impostazione predefinita) Suddivide markdown in più documenti di ricerca, ognuno dei quali rappresenta una sezione di contenuto (nonheader) del file Markdown. È possibile omettere "submode" a meno che non si voglia un'analisi uno-a-uno.
markdown oneToOne Uno per BLOB Analizza il Markdown in un unico documento di ricerca, con le sezioni mappate a intestazioni specifiche nel file Markdown.

Per la submode oneToMany, è necessario prendere in esame Indicizzazione di un BLOB per produrre molti documenti di ricerca per comprendere il modo in cui l'indicizzatore BLOB gestisce la disambiguazione della chiave del documento per più documenti di ricerca generati dallo stesso BLOB.

Le sezioni successive descrivono ogni sottomodo in modo più dettagliato. Se non si ha familiarità con i client e i concetti dell'indicizzatore, vedere Creare un indicizzatore di ricerca. È anche necessario avere familiarità con i dettagli della configurazione dell'indicizzatore BLOB di base, che non viene ripetuta qui.

Parametri di analisi Markdown facoltativi

I parametri sono case sensitive.

Nome del parametro Valori consentiti Descrizione
markdownHeaderDepth h1, h2, h3, h4, h5h6 (default) Questo parametro determina il livello di intestazione più profondo che viene considerato durante l'analisi, consentendo la gestione flessibile della struttura del documento (ad esempio, quando markdownHeaderDepth è impostato su h1, il parser riconosce solo le intestazioni di primo livello che iniziano con "#" e tutte le intestazioni di livello inferiore vengono considerate come testo normale). Se non specificato, per impostazione predefinita viene impostato su h6.

Questa impostazione può essere modificata dopo la creazione dell'indicizzatore. Tuttavia, la struttura dei documenti di ricerca risultanti potrebbe cambiare a seconda del contenuto Markdown.

Elementi Markdown supportati

L'analisi markdown suddivide solo il contenuto in base alle intestazioni. Tutti gli altri elementi, ad esempio elenchi, blocchi di codice e tabelle, vengono considerati come testo normale e passati in un campo di contenuto.

Contenuto markdown di esempio

Il contenuto Markdown seguente viene usato per gli esempi in questa pagina:

# Section 1
Content for section 1.

## Subsection 1.1
Content for subsection 1.1.

# Section 2
Content for section 2.

Usare la modalità di analisi uno-a-molti

La modalità di analisi uno-a-molti analizza i file Markdown in più documenti di ricerca, in cui ogni documento corrisponde a una sezione di contenuto specifica del file Markdown in base ai metadati dell'intestazione in quel punto del documento. Il Markdown viene analizzato sulla base delle intestazioni in documenti di ricerca, che contengono il contenuto seguente.

  • content: stringa contenente il markdown non elaborato trovato in una posizione specifica, in base ai metadati dell'intestazione in quel punto del documento.

  • sections: oggetto che contiene campi secondari per i metadati dell'intestazione fino al livello di intestazione desiderato. Ad esempio, quando markdownHeaderDepth è impostato su h3, contiene i campi stringa h1, h2 e h3. Questi campi vengono indicizzati eseguendo il mirroring di questa struttura nell'indice o tramite mapping dei campi nel formato /sections/h1, /sections/h2e così via. Per esempi di contesto, vedere le configurazioni dell'indice e dell'indicizzatore negli esempi seguenti. I sottocampi contenuti sono:

    • h1 - Stringa contenente il valore dell'intestazione h1. Stringa vuota se non impostata a questo punto del documento.
    • (Facoltativo) h2- Stringa contenente il valore dell'intestazione h2. Stringa vuota se non impostata a questo punto del documento.
    • (Facoltativo) h3- Stringa contenente il valore dell'intestazione h3. Stringa vuota se non impostata a questo punto del documento.
    • (Facoltativo) h4- Stringa contenente il valore dell'intestazione h4. Stringa vuota se non impostata a questo punto del documento.
    • (Facoltativo) h5- Stringa contenente il valore dell'intestazione h5. Stringa vuota se non impostata a questo punto del documento.
    • (Facoltativo) h6- Stringa contenente il valore dell'intestazione h6. Stringa vuota se non impostata a questo punto del documento.
  • ordinal_position: valore intero che indica la posizione della sezione all'interno della gerarchia del documento. Questo campo viene usato per ordinare le sezioni nella sequenza originale come appaiono nel documento, a partire da una posizione ordinale di 1 e incrementando in sequenza per ogni intestazione.

Schema dell'indice per l'analisi uno-a-molti

Una configurazione di indice di esempio potrebbe essere simile alla seguente:

{
  "name": "my-markdown-index",
  "fields": [
  {
    "name": "id",
    "type": "Edm.String",
    "key": true
  },
  {
    "name": "content",
    "type": "Edm.String",
  },
  {
    "name": "ordinal_position",
    "type": "Edm.Int32"
  },
  {
    "name": "sections",
    "type": "Edm.ComplexType",
    "fields": [
    {
      "name": "h1",
      "type": "Edm.String"
    },
    {
      "name": "h2",
      "type": "Edm.String"
    }]
  }]
}

Definizione dell'indicizzatore per analisi del tipo uno-a-molti

Se i nomi dei campi e i tipi di dati sono allineati, l'indicizzatore BLOB può dedurre il mapping senza un mapping di campo esplicito presente nella richiesta, pertanto una configurazione dell'indicizzatore corrispondente alla configurazione dell'indice fornita potrebbe essere simile alla seguente:

POST https://[service name].search.windows.net/indexers?api-version=2026-04-01
Content-Type: application/json
api-key: [admin key]

{
  "name": "my-markdown-indexer",
  "dataSourceName": "my-blob-datasource",
  "targetIndexName": "my-target-index",
  "parameters": {
    "configuration": { "parsingMode": "markdown" }
  },
}

Nota

submode Non è necessario impostare in modo esplicito qui perché oneToMany è l'impostazione predefinita.

Output dell'indicizzatore per l'analisi uno-a-molti

Questo file Markdown genera tre documenti di ricerca dopo l'indicizzazione, a causa delle tre sezioni di contenuto. Il documento di ricerca risultante dalla prima sezione contenuto del documento Markdown fornito conterrà i valori seguenti per content, sectionsh1, e h2:

{
  {
    "content": "Content for section 1.\r\n",
    "sections": {
      "h1": "Section 1",
      "h2": ""
    },
    "ordinal_position": 1
  },
  {
    "content": "Content for subsection 1.1.\r\n",
    "sections": {
      "h1": "Section 1",
      "h2": "Subsection 1.1"
    },
    "ordinal_position": 2
  },
  {
    "content": "Content for section 2.\r\n",
    "sections": {
      "h1": "Section 2",
      "h2": ""
    },
    "ordinal_position": 3
  }
}

Eseguire il mapping di campi uno-a-molti in un indice di ricerca

I mapping dei campi associano un campo di origine a un campo di destinazione in situazioni in cui i nomi dei campi e i tipi non sono identici. Ma i mapping dei campi possono essere usati anche per trovare le corrispondenze tra parti di un documento Markdown e "sollevarle" in campi di primo livello del documento di ricerca.

Nell'esempio seguente viene illustrato questo scenario. Per altre informazioni sui mapping dei campi in generale, vedere Mapping dei campi.

Si supponga che un indice di ricerca con i campi seguenti: raw_content di tipo Edm.String, h1_header di tipo Edm.Stringe h2_header di tipo Edm.String. Per eseguire il mapping del Markdown nella forma desiderata, utilizzare i seguenti mapping dei campi:

"fieldMappings" : [
    { "sourceFieldName" : "/content", "targetFieldName" : "raw_content" },
    { "sourceFieldName" : "/sections/h1", "targetFieldName" : "h1_header" },
    { "sourceFieldName" : "/sections/h2", "targetFieldName" : "h2_header" },
  ]

Il documento di ricerca risultante nell'indice sarà simile al seguente:

{
  {
    "raw_content": "Content for section 1.\r\n",
    "h1_header": "Section 1",
    "h2_header": "",
  },
  {
    "raw_content": "Content for section 1.1.\r\n",
    "h1_header": "Section 1",
    "h2_header": "Subsection 1.1",
  },
  {
    "raw_content": "Content for section 2.\r\n",
    "h1_header": "Section 2",
    "h2_header": "",
  }
}

Usare la modalità di analisi uno-a-uno

Nella modalità di analisi uno-a-uno, l'intero documento Markdown viene indicizzato come un singolo documento di ricerca, mantenendo la gerarchia e la struttura del contenuto originale. Questa modalità è più utile quando i file da indicizzare condividono una struttura comune, in modo da poter usare questa struttura comune nell'indice per rendere i campi pertinenti ricercabili.

Nella definizione dell'indicizzatore impostare parsingMode su "markdown" e usare il parametro facoltativo markdownHeaderDepth per definire la profondità massima dell'intestazione per la suddivisione in blocchi. Se non specificato, il valore predefinito è h6, acquisendo tutte le possibili profondità delle intestazioni.

Il Markdown viene analizzato sulla base delle intestazioni in documenti di ricerca, che contengono il contenuto seguente.

  • document_content: contiene il testo markdown completo come singola stringa. Questo campo funge da rappresentazione non elaborata del documento di input.

  • sections: matrice di oggetti che contiene la rappresentazione gerarchica delle sezioni all'interno del documento Markdown. Ogni sezione viene rappresentata come oggetto all'interno di questa matrice e acquisisce la struttura del documento in modo annidato corrispondente alle intestazioni e al rispettivo contenuto. I campi sono accessibili tramite mapping dei campi facendo riferimento al percorso, ad esempio /sections/content. Gli oggetti in questa matrice hanno le proprietà seguenti:

    • header_level: stringa che indica il livello dell'intestazione (h1, h2, h3e così via) nella sintassi markdown. Questo campo consente di comprendere la gerarchia e la strutturazione del contenuto.

    • header_name: Una stringa contenente il testo dell'intestazione così come appare nel documento Markdown. Questo campo fornisce un'etichetta o un titolo per la sezione.

    • content: stringa contenente contenuto di testo che segue immediatamente l'intestazione, fino all'intestazione successiva. Questo campo acquisisce le informazioni dettagliate o la descrizione associata all'intestazione. Se non è presente alcun contenuto direttamente in un'intestazione, il valore è una stringa vuota.

    • ordinal_position: valore intero che indica la posizione della sezione all'interno della gerarchia del documento. Questo campo viene usato per ordinare le sezioni nella sequenza originale come appaiono nel documento, a partire da una posizione ordinale di 1 e incrementando in sequenza per ogni blocco di contenuto.

    • sections: matrice che contiene oggetti che rappresentano sottosezioni annidate nella sezione corrente. Questa matrice segue la stessa struttura della matrice di primo livello sections , consentendo la rappresentazione di più livelli di contenuto annidato. Ogni oggetto sottosezione include header_level, header_name, content e ordinal_position proprietà, permettendo una struttura ricorsiva che rappresenta la gerarchia del contenuto Markdown.

Ecco l'esempio markdown usato per spiegare gli schemi di indice progettati per ogni modalità di analisi.

# Section 1
Content for section 1.

## Subsection 1.1
Content for subsection 1.1.

# Section 2
Content for section 2.

Schema dell'indice per l'analisi uno-a-uno

Se non si usano mapping di campi, la forma dell'indice deve riflettere la forma del contenuto Markdown. Data la struttura dell'esempio Markdown con le due sezioni e la sottosezione singola, l'indice dovrebbe essere simile all'esempio seguente:

{
  "name": "my-markdown-index",
  "fields": [
  {
    "name": "id",
    "type": "Edm.String",
    "key": true
  },
  {
    "name": "document_content",
    "type": "Edm.String"
  },
  {
    "name": "sections",
    "type": "Collection(Edm.ComplexType)",
    "fields": [
    {
      "name": "header_level",
      "type": "Edm.String"
    },
    {
      "name": "header_name",
      "type": "Edm.String"
    },
    {
      "name": "content",
      "type": "Edm.String"
    },
    {
      "name": "ordinal_position",
      "type": "Edm.Int32"
    },
    {
      "name": "sections",
      "type": "Collection(Edm.ComplexType)",
      "fields": [
      {
        "name": "header_level",
        "type": "Edm.String"
      },
      {
        "name": "header_name",
        "type": "Edm.String"
      },
      {
        "name": "content",
        "type": "Edm.String"
      },
      {
        "name": "ordinal_position",
        "type": "Edm.Int32"
      }]
    }]
  }]
}

Definizione dell'indicizzatore per l'analisi uno-a-uno

POST https://[service name].search.windows.net/indexers?api-version=2026-04-01
Content-Type: application/json
api-key: [admin key]

{
  "name": "my-markdown-indexer",
  "dataSourceName": "my-blob-datasource",
  "targetIndexName": "my-target-index",
  "parameters": {
    "configuration": {
      "parsingMode": "markdown",
      "markdownParsingSubmode": "oneToOne",
    }
  }
}

Output dell'indicizzatore per l'analisi uno-a-uno

Poiché il markdown che si vuole indicizzare passa solo a una profondità di h2 ("##"), sono necessari sections campi annidati a una profondità pari a 2 per trovare una corrispondenza. Questa configurazione genera i dati seguenti nell'indice:

  "document_content": "# Section 1\r\nContent for section 1.\r\n## Subsection 1.1\r\nContent for subsection 1.1.\r\n# Section 2\r\nContent for section 2.\r\n",
  "sections": [
    {
      "header_level": "h1",
      "header_name": "Section 1",
      "content": "Content for section 1.",
      "ordinal_position": 1,
      "sections": [
        {
          "header_level": "h2",
          "header_name": "Subsection 1.1",
          "content": "Content for subsection 1.1.",
          "ordinal_position": 2,
        }]
    }],
    {
      "header_level": "h1",
      "header_name": "Section 2",
      "content": "Content for section 2.",
      "ordinal_position": 3,
      "sections": []
    }]
  }

Come si può notare, la posizione ordinale aumenta in base alla posizione del contenuto all'interno del documento.

Se i livelli di intestazione vengono ignorati nel contenuto, la struttura del documento risultante riflette le intestazioni presenti nel contenuto Markdown e non contiene necessariamente sezioni annidate consecutive da h1 a h6. Ad esempio, quando il documento inizia a h2, il primo elemento nell'array delle sezioni di primo livello è h2.

Mappare uno-a-uno i campi in un indice di ricerca

Per estrarre campi con nomi personalizzati dal documento, è possibile usare i mapping dei campi. Usando lo stesso esempio Markdown di prima, prendere in considerazione la configurazione dell'indice seguente:

{
  "name": "my-markdown-index",
  "fields": [
    {
      "name": "document_content",
      "type": "Edm.String",
    },
    {
      "name": "document_title",
      "type": "Edm.String",
    },
    {
      "name": "opening_subsection_title",
      "type": "Edm.String"
    },
    {
      "name": "summary_content",
      "type": "Edm.String",
    }
  ]
}

L'estrazione di campi specifici dal Markdown analizzato viene gestita in modo simile a come i percorsi dei documenti si trovano in outputFieldMappings, ad eccezione del percorso che inizia con /sections invece di /document. Ad esempio, /sections/0/content corrisponderà al contenuto sotto l'elemento nella posizione 0 nell'array delle sezioni.

Un esempio di caso d'uso sicuro potrebbe essere simile al seguente: tutti i file Markdown hanno un titolo del documento nel primo h1, un titolo di sottosezione nel primo h2e un riepilogo nel contenuto del paragrafo finale sotto l'ultimo h1. È possibile usare i mapping dei campi seguenti per indicizzare solo il contenuto:

"fieldMappings" : [
  { "sourceFieldName" : "/content", "targetFieldName" : "raw_content" },
  { "sourceFieldName" : "/sections/0/header_name", "targetFieldName" : "document_title" },
  { "sourceFieldName" : "/sections/0/sections/header_name", "targetFieldName" : "opening_subsection_title" },
  { "sourceFieldName" : "/sections/1/content", "targetFieldName" : "summary_content" },
]

In questo caso, si estraggono solo le parti pertinenti da tale documento. Per usare in modo più efficace questa funzionalità, i documenti che si prevede di indicizzare devono condividere la stessa struttura di intestazione gerarchica.

Il documento di ricerca risultante nell'indice sarà simile al seguente:

{
  "content": "Content for section 1.\r\n",
  "document_title": "Section 1",
  "opening_subsection_title": "Subsection 1.1",
  "summary_content": "Content for section 2."
}

Nota

Questi esempi specificano come usare queste modalità di analisi interamente con o senza mapping dei campi, ma è possibile applicare entrambi in uno scenario se adatto alle proprie esigenze.

Gestire i documenti obsoleti dalla reindicizzazione Markdown

Quando si usa la modalità di analisi uno-a-molti, la reindicizzazione di un file Markdown modificato può comportare documenti obsoleti o duplicati se le sezioni vengono rimosse. Questo comportamento è specifico della modalità uno-a-molti e non si applica all'analisi uno-a-uno.

Panoramica del comportamento

Modalità di analisi uno-a-molti

In oneToMany modalità, ogni sezione Markdown (basata sulle intestazioni) viene indicizzata come documento di ricerca separato. Quando il file viene ri-indicizzato:

  • Nessuna eliminazione automatica: l'indicizzatore sovrascrive i documenti esistenti con quelli nuovi, ma non elimina i documenti che non corrispondono più ad alcun contenuto nel file aggiornato.
  • Potenziale di duplicati: questo problema si verifica in modo specifico solo quando vengono eliminate più sezioni rispetto all'inserimento tra esecuzioni di indicizzazione. In questi casi, i documenti lasciati dalla versione precedente rimangono nell'indice, causando voci non aggiornate che non riflettono più lo stato corrente del file di origine.

Modalità di analisi uno-a-uno

In oneToOne modalità, l'intero file Markdown viene indicizzato come singolo documento di ricerca. Quando il file viene ri-indicizzato:

  • Comportamento di sovrascrittura: il documento esistente viene sostituito interamente con la nuova versione.
  • Nessuna sezione non aggiornata: quando il file viene ri-indicizzato, il documento esistente viene sostituito con la versione aggiornata e il contenuto rimosso non è più incluso. L'unica eccezione è se il percorso del file o l'URI BLOB cambia, il che potrebbe comportare la creazione di un nuovo documento insieme a quello precedente.

Opzioni alternative

Per garantire che l'indice rifletta lo stato corrente dei file Markdown, considerare uno degli approcci seguenti:

Opzione 1. Eliminazione temporanea con metadati

Questo metodo utilizza un'eliminazione morbida per eliminare i documenti associati a un BLOB specifico. Per ulteriori informazioni, vedere il rilevamento delle modifiche e delle eliminazioni utilizzando indicizzatori in Azure AI Search per Archiviazione di Azure.

Passi:

  1. Contrassegnare il BLOB come eliminato impostando un campo di metadati.
  2. Consentire l'esecuzione dell'indicizzatore. Elimina tutti i documenti nell'indice associato a tale BLOB.
  3. Rimuovere il marcatore di eliminazione temporanea e ri indicizzare il file.

Opzione 2. Utilizzare l'API delete

Prima di reindicizzare un file Markdown modificato, eliminare in modo esplicito i documenti esistenti associati a tale file usando l'API di eliminazione. È possibile:

  • Identificare manualmente i singoli documenti non aggiornati identificando i duplicati nell'indice da eliminare. Questo può essere fattibile per piccole e ben comprese modifiche, ma può richiedere molto tempo.
  • (Scelta consigliata) Rimuovere tutti i documenti generati dallo stesso file padre prima di reindicizzare, assicurandosi che le incoerenze vengano evitate.

Passi:

  1. Identificare l'ID dei documenti associati al file. Usare una query come l'esempio seguente per recuperare gli ID chiave del documento (ad esempio, id o chunk_id) per tutti i documenti associati a un file specifico. Sostituire metadata_storage_path con il campo appropriato nell'indice mappato al percorso del file o all'URI del BLOB. Questo campo deve essere una chiave.

    GET https://[service name].search.windows.net/indexes/[index name]/docs?api-version=2026-04-01
    Content-Type: application/json
    api-key: [admin key]
    
    
      {
          "filter": "metadata_storage_path eq 'https://<storage-account>.blob.core.windows.net/<container-name>/<file-name>.md'",
          "select": "id"
      }
    
  2. Eseguire una richiesta di eliminazione per i documenti con le chiavi identificate.

    POST https://[service name].search.windows.net/indexes/[index name]/docs/index?api-version=2026-04-01
    Content-Type: application/json
    api-key: [admin key]
    
    {
      "value": [
        {
          "@search.action": "delete",
          "id": "aHR0c...jI1"
        },
        {
          "@search.action": "delete",
          "id": "aHR0...MQ2"
        }
      ]
    }
    
  3. Reindicizza il file aggiornato.

Passaggi successivi