Tutorial: Indexación de blobs de Markdown anidados desde Azure Storage mediante REST

Búsqueda de Azure AI puede indexar documentos y matrices de Markdown en Azure Blob Storage mediante un indexer que sabe cómo leer datos de Markdown.

En este tutorial se muestra cómo indexar archivos de Markdown mediante el oneToMany modo de análisis de Markdown y las API REST del servicio de búsqueda.

En este tutorial, tú:

  • Configura datos de ejemplo y establece un azureblob origen de datos
  • Creación de un índice de Búsqueda de Azure AI para contener contenido que se puede buscar
  • Creación y ejecución de un indexador para leer el contenedor y extraer contenido que se puede buscar
  • Busque el índice que acaba de crear.

Requisitos previos

Nota

Puede usar un servicio de búsqueda gratuito para este tutorial. El nivel Gratis le limita a tres índices, tres indexadores y tres orígenes de datos. En este tutorial se crea uno de cada uno de ellos. Antes de empezar, asegúrese de que el servicio tiene espacio para aceptar los nuevos recursos.

Preparación de datos de ejemplo

Creación de un archivo Markdown

Copie y pegue el siguiente Markdown en un archivo denominado sample_markdown.md. Los datos de ejemplo son un único archivo Markdown que contiene varios elementos markdown. Hemos elegido un archivo Markdown para permanecer bajo los límites de almacenamiento del nivel Gratis.

# Project Documentation

## Introduction
This document provides a complete overview of the **Markdown Features** used within this project. The following sections demonstrate the richness of Markdown formatting, with examples of lists, tables, links, images, blockquotes, inline styles, and more.

---

## Table of Contents
1. [Headers](#headers)
2. [Introduction](#introduction)
3. [Basic Text Formatting](#basic-text-formatting)
4. [Lists](#lists)
5. [Blockquotes](#blockquotes)
6. [Images](#images)
7. [Links](#links)
8. [Tables](#tables)
9. [Code Blocks and Inline Code](#code-blocks-and-inline-code)
10. [Horizontal Rules](#horizontal-rules)
11. [Inline Elements](#inline-elements)
12. [Escaping Characters](#escaping-characters)
13. [HTML Elements](#html-elements)
14. [Emojis](#emojis)
15. [Footnotes](#footnotes)
16. [Task Lists](#task-lists)
17. [Conclusion](#conclusion)

---

## Headers
Markdown supports six levels of headers. Use `#` to create headers:
"# Project Documentation" at the top of the document is an example of an h1 header.
"## Headers" above is an example of an h2 header.
### h3 example
#### h4 example
##### h5 example
###### h6 example
This is an example of content underneath a header.

## Basic Text Formatting
You can apply various styles to your text:
- **Bold**: Use double asterisks or underscores: `**bold**` or `__bold__`.
- *Italic*: Use single asterisks or underscores: `*italic*` or `_italic_`.
- ~~Strikethrough~~: Use double tildes: `~~strikethrough~~`.

## Lists

### Ordered List
1. First item  
2. Second item  
3. Third item  

### Unordered List
- Item A  
- Item B  
- Item C  

### Nested List
1. Parent item  
   - Child item  
   - Child item  

## Blockquotes
> This is a blockquote.  
> Blockquotes are great for emphasizing important information.  
>> Nested blockquotes are also possible!

## Images
![Markdown Logo](https://markdown-here.com/img/icon256.png)

## Links
[Visit Markdown Guide](https://www.markdownguide.org)

## Tables

| Syntax      | Description | Example       |
|-------------|-------------|---------------|
| Header      | Title       | Header Cell   |
| Paragraph   | Text block  | Row Content   |

## Code Blocks and Inline Code

### Inline Code
Use backticks to create `inline code`.

### Code Block
```javascript
// JavaScript example
function greet(name) {
  console.log(`Hello, ${name}!`);
}
greet('World');
```

## Horizontal Rules
Use three or more dashes or underscores to create a horizontal rule.

---
___

## Inline Elements
Sometimes, it’s useful to include `inline code` to highlight code-like content.  

You can also emphasize text like *this* or make it **bold**.

## Escaping Characters
To render special Markdown characters, use backslashes:
- \*Asterisks\*
- \#Hashes\#
- \[Brackets\]

## HTML Elements
You can mix HTML tags with Markdown:

<table>
  <tr>
    <th>HTML Table</th>
    <th>With Markdown</th>
  </tr>
  <tr>
    <td>Row 1</td>
    <td>Data 1</td>
  </tr>
</table>

## Emojis
Markdown supports some basic emojis:
- :smile: 😄  
- :rocket: 🚀  
- :checkered_flag: 🏁  

## Footnotes
This is an example of a footnote[^1]. Footnotes allow you to add notes without cluttering the main text.

[^1]: This is the content of the footnote.

## Task Lists
- [x] Complete the introduction  
- [ ] Add more examples  
- [ ] Review the document 

## Conclusion
Markdown is a lightweight yet powerful tool for writing documentation. It supports a variety of formatting options while maintaining simplicity and readability.

Thank you for reviewing this example!

Sube el archivo y obtén una cadena de conexión

Siga estas instrucciones para cargar el sample_markdown.md archivo en un contenedor de su Cuenta de Almacenamiento de Azure. También debe obtener la cadena de conexión de la cuenta de almacenamiento. Anote el cadena de conexión y el nombre del contenedor para su uso posterior.

Copia de una dirección URL del servicio de búsqueda y una clave de API

Para este tutorial, las conexiones a Búsqueda de Azure AI requieren un punto de conexión y una clave de API. Puede obtener estos valores desde el portal de Azure. Para obtener métodos de conexión alternativos, consulte Identidades administradas.

  1. Vaya al servicio de búsqueda en el portal Azure.

  2. En el panel izquierdo, seleccione Información general.

  3. Anote la dirección URL, que debería tener un aspecto similar a https://my-service.search.windows.net.

  4. En el panel izquierdo, seleccione Claves de configuración>.

  5. Anote una clave de administrador para obtener derechos completos en el servicio. Hay dos claves de administración intercambiables, proporcionadas para la continuidad empresarial en caso de que necesite revertir una. Puede usar cualquiera de las dos claves en los requerimientos para agregar, modificar y eliminar objetos.

    Captura de pantalla de la dirección URL y las claves de API en el portal de Azure.

Configuración del archivo REST

  1. Cree un archivo en Visual Studio Code.

  2. Proporcione valores para las variables usadas en la solicitud.

    @baseUrl = PUT-YOUR-SEARCH-SERVICE-ENDPOINT-HERE
    @apiKey = PUT-YOUR-ADMIN-API-KEY-HERE
    @storageConnectionString = PUT-YOUR-STORAGE-CONNECTION-STRING-HERE
    @blobContainer = PUT-YOUR-CONTAINER-NAME-HERE
    
  3. Guarde el archivo usando una extensión de archivo .rest o .http.

Para obtener ayuda con el cliente REST, consulte Inicio rápido: Búsqueda de texto completo mediante REST.

Creación de un origen de datos

Orígenes de datos: crear (API REST) crea una conexión de origen de datos que especifica qué datos se van a indexar.

### Create a data source
POST {{baseUrl}}/datasources?api-version=2026-04-01  HTTP/1.1
Content-Type: application/json
api-key: {{apiKey}}

{
    "name" : "sample-markdown-ds",
    "description": null,
    "type": "azureblob",
    "subtype": null,
    "credentials": {
        "connectionString": "{{storageConnectionString}}"
    },
    "container": {
        "name": "{{blobContainer}}",
        "query": null
    },
    "dataChangeDetectionPolicy": null,
    "dataDeletionDetectionPolicy": null
}

Envíe la solicitud. La respuesta debe ser similar a la siguiente:

HTTP/1.1 201 Created
Transfer-Encoding: chunked
Content-Type: application/json; odata.metadata=minimal; odata.streaming=true; charset=utf-8
ETag: "0x8DCF52E926A3C76"
Location: https://<YOUR-SEARCH-SERVICE-NAME>.search.windows.net:443/datasources('sample-markdown-ds')?api-version=2026-04-01
Server: Microsoft-IIS/10.0
Strict-Transport-Security: max-age=2592000, max-age=15724800; includeSubDomains
Preference-Applied: odata.include-annotations="*"
OData-Version: 4.0
request-id: 0714c187-217e-4d35-928a-5069251e5cba
elapsed-time: 204
Date: Fri, 25 Oct 2024 19:52:35 GMT
Connection: close

{
  "@odata.context": "https://<YOUR-SEARCH-SERVICE-NAME>.search.windows.net/$metadata#datasources/$entity",
  "@odata.etag": "\"0x8DCF52E926A3C76\"",
  "name": "sample-markdown-ds",
  "description": null,
  "type": "azureblob",
  "subtype": null,
  "credentials": {
    "connectionString": null
  },
  "container": {
    "name": "markdown-container",
    "query": null
  },
  "dataChangeDetectionPolicy": null,
  "dataDeletionDetectionPolicy": null,
  "encryptionKey": null,
  "identity": null
}

Creación de un índice

Índices: crear (API REST) crea un índice de búsqueda en el servicio de búsqueda. Un índice especifica todos los campos y sus atributos.

En el análisis de uno a varios, el documento de búsqueda define el lado "varios" de la relación. Los campos que especifique en el índice determinan la estructura del documento de búsqueda.

Solo necesita campos para los elementos Markdown que admite el analizador. Estos campos son:

  • content: Una cadena que contiene el Markdown sin procesar que se encuentra en una ubicación específica, basada en los metadatos del encabezado en ese punto del documento.

  • sections: objeto que contiene subcampos para los metadatos de encabezado hasta el nivel de encabezado deseado. Por ejemplo, cuando markdownHeaderDepth se establece en h3, contiene campos de cadena h1, h2 y h3. Estos campos se indexan mediante la creación de reflejo de esta estructura en el índice, o mediante asignaciones de campos con el formato /sections/h1, /sections/h2, etc. Para ver ejemplos en contexto, consulte las configuraciones de índice e indexador en los ejemplos siguientes. Los subcampos incluidos son:

    • h1 - Cadena que contiene el valor del encabezado h1. Cadena vacía si no se establece en este punto del documento.
    • (Opcional) h2- Cadena que contiene el valor del encabezado h2. Cadena vacía si no se establece en este punto del documento.
    • (Opcional) h3- Cadena que contiene el valor del encabezado h3. Cadena vacía si no se establece en este punto del documento.
    • (Opcional) h4- Cadena que contiene el valor del encabezado h4. Cadena vacía si no se establece en este punto del documento.
    • (Opcional) h5- Cadena que contiene el valor del encabezado h5. Cadena vacía si no se establece en este punto del documento.
    • (Opcional) h6- Cadena que contiene el valor del encabezado h6. Cadena vacía si no se establece en este punto del documento.
  • ordinal_position: valor entero que indica la posición de la sección dentro de la jerarquía de documentos. Este campo se usa para ordenar las secciones de su secuencia original tal como aparecen en el documento, empezando por una posición ordinal de 1 e incrementando secuencialmente para cada bloque de contenido.

Esta implementación utiliza mapeos de campos en el indexador para conectar el contenido enriquecido con el índice. Para obtener más información sobre la estructura del documento de uno a muchos analizada, consulte Index Markdown blobs.

En este ejemplo se proporcionan ejemplos de cómo indexar datos con y sin asignaciones de campos. En este caso, h1 contiene el título del documento y se asigna a un campo denominado title. h2 y h3 asignan los campos a h2_subheader y h3_subheader, respectivamente. Los campos content y ordinal_position no requieren ninguna asignación porque se extraen del Markdown directamente a campos con esos nombres. Para obtener un ejemplo de un esquema de índice completo que no requiere asignaciones de campos, consulte el final de esta sección.

### Create an index
POST {{baseUrl}}/indexes?api-version=2026-04-01  HTTP/1.1
Content-Type: application/json
api-key: {{apiKey}}

{
  "name": "sample-markdown-index",  
  "fields": [
    {"name": "id", "type": "Edm.String", "key": true, "searchable": true, "retrievable": true, "filterable": true, "facetable": true, "sortable": true},
    {"name": "content", "type": "Edm.String", "key": false, "searchable": true, "retrievable": true, "filterable": true, "facetable": true, "sortable": true},
    {"name": "title", "type": "Edm.String", "searchable": true, "retrievable": true, "filterable": true, "facetable": true, "sortable": true},
    {"name": "h2_subheader", "type": "Edm.String", "searchable": true, "retrievable": true, "filterable": true, "facetable": true, "sortable": true},
    {"name": "h3_subheader", "type": "Edm.String", "searchable": true, "retrievable": true, "filterable": true, "facetable": true, "sortable": true},
    {"name": "ordinal_position", "type": "Edm.Int32", "searchable": false, "retrievable": true, "filterable": true, "facetable": true, "sortable": true}
  ]
}

Esquema de índice en una configuración sin asignaciones de campos

Las asignaciones de campos permiten manipular y filtrar el contenido enriquecido para adaptarse a la forma deseada del índice. Sin embargo, usted podría simplemente querer tomar el contenido enriquecido directamente. En ese caso, el esquema tendría el siguiente aspecto:

{
  "name": "sample-markdown-index",
  "fields": [
    {"name": "id", "type": "Edm.String", "key": true, "searchable": true, "retrievable": true, "filterable": true, "facetable": true, "sortable": true},
    {"name": "content", "type": "Edm.String", "key": false, "searchable": true, "retrievable": true, "filterable": true, "facetable": true, "sortable": true},
    {"name": "sections", 
      "type": "Edm.ComplexType", 
      "fields": [
        {"name": "h1", "type": "Edm.String", "searchable": true, "retrievable": true, "filterable": true, "facetable": true, "sortable": true},
        {"name": "h2", "type": "Edm.String", "searchable": true, "retrievable": true, "filterable": true, "facetable": true, "sortable": true},
        {"name": "h3", "type": "Edm.String", "searchable": true, "retrievable": true, "filterable": true, "facetable": true, "sortable": true}
      ]
    },
    {"name": "ordinal_position", "type": "Edm.Int32", "searchable": false, "retrievable": true, "filterable": true, "facetable": true, "sortable": true}
  ]
}

Para reiterar, tenemos subcampos hasta h3 en el objeto sections porque markdownHeaderDepth está establecido en h3.

Si usa este esquema, asegúrese de ajustar las solicitudes posteriores en consecuencia. Para ello, es necesario quitar las asignaciones de campos de la configuración del indexador y actualizar las consultas de búsqueda para usar los nombres de campo correspondientes.

Creación y ejecución de un indexador

Indexadores: crear (API REST) crea un indexador en el servicio de búsqueda. Un indexador se conecta al origen de datos, carga e indexa datos y, opcionalmente, proporciona una programación para automatizar la actualización de datos.

### Create and run an indexer
POST {{baseUrl}}/indexers?api-version=2026-04-01  HTTP/1.1
Content-Type: application/json
api-key: {{apiKey}}

{
  "name": "sample-markdown-indexer",
  "dataSourceName": "sample-markdown-ds",
  "targetIndexName": "sample-markdown-index",
  "parameters" : { 
    "configuration": { 
      "parsingMode": "markdown",
      "markdownParsingSubmode": "oneToMany",
      "markdownHeaderDepth": "h3"
      }
    },
  "fieldMappings" : [ 
    {
      "sourceFieldName": "/sections/h1",
      "targetFieldName": "title",
      "mappingFunction": null
    }
  ]
}

Puntos clave:

  • El indexador analiza solo los encabezados hasta h3. Los encabezados de nivel inferior (h4,h5,h6) se tratan como texto sin formato y se muestran en el content campo. Este es el motivo por el que los índices y las asignaciones de campos solo existen hasta una profundidad de h3.

  • Los campos content y ordinal_position no requieren ninguna asignación de campos porque existen con esos nombres en el contenido enriquecido.

Ejecutar consultas

Puede empezar a buscar en cuanto se cargue el primer documento.

### Query the index
POST {{baseUrl}}/indexes/sample-markdown-index/docs/search?api-version=2026-04-01  HTTP/1.1
Content-Type: application/json
api-key: {{apiKey}}
  
{
  "search": "*",
  "count": true
}

Envíe la solicitud. Se trata de una consulta de búsqueda de texto completo no especificada que devuelve todos los campos marcados como recuperables en el índice, junto con un recuento de documentos. La respuesta debe ser similar a la siguiente:

HTTP/1.1 200 OK
Transfer-Encoding: chunked
Content-Type: application/json; odata.metadata=minimal; odata.streaming=true; charset=utf-8
Content-Encoding: gzip
Vary: Accept-Encoding
Server: Microsoft-IIS/10.0
Strict-Transport-Security: max-age=2592000, max-age=15724800; includeSubDomains
Preference-Applied: odata.include-annotations="*"
OData-Version: 4.0
request-id: 6b94e605-55e8-47a5-ae15-834f926ddd14
elapsed-time: 77
Date: Fri, 25 Oct 2024 20:22:58 GMT
Connection: close

{
  "@odata.context": "https://<YOUR-SEARCH-SERVICE-NAME>.search.windows.net/indexes('sample-markdown-index')/$metadata#docs(*)",
  "@odata.count": 22,
  "value": [
    <22 search documents here>
  ]
}

Agregue un search parámetro para buscar una cadena.

### Query the index
POST {{baseUrl}}/indexes/sample-markdown-index/docs/search?api-version=2026-04-01  HTTP/1.1
Content-Type: application/json
api-key: {{apiKey}}
  
{
  "search": "h4",
  "count": true
}

Envíe la solicitud. La respuesta debe ser similar a la siguiente:

HTTP/1.1 200 OK
Transfer-Encoding: chunked
Content-Type: application/json; odata.metadata=minimal; odata.streaming=true; charset=utf-8
Content-Encoding: gzip
Vary: Accept-Encoding
Server: Microsoft-IIS/10.0
Strict-Transport-Security: max-age=2592000, max-age=15724800; includeSubDomains
Preference-Applied: odata.include-annotations="*"
OData-Version: 4.0
request-id: ec5d03f1-e3e7-472f-9396-7ff8e3782105
elapsed-time: 52
Date: Fri, 25 Oct 2024 20:26:29 GMT
Connection: close

{
  "@odata.context": "https://<YOUR-SEARCH-SERVICE-NAME>.search.windows.net/indexes('sample-markdown-index')/$metadata#docs(*)",
  "@odata.count": 1,
  "value": [
    {
      "@search.score": 0.8744742,
      "section_id": "aHR0cHM6Ly9hcmphZ2Fubmpma2ZpbGVzLmJsb2IuY29yZS53aW5kb3dzLm5ldC9tYXJrZG93bi10dXRvcmlhbC9zYW1wbGVfbWFya2Rvd24ubWQ7NA2",
      "content": "#### h4 example\r\n##### h5 example\r\n###### h6 example\r\nThis is an example of content underneath a header.\r\n",
      "title": "Project Documentation",
      "h2_subheader": "Headers",
      "h3_subheader": "h3 example",
      "ordinal_position": 4
    }
  ]
}

Puntos clave:

  • Dado que el markdownHeaderDepth está establecido en h3, los encabezados h4, h5 y h6 se tratan como texto sin cifrar, por lo que aparecen en el campo content.

  • La posición ordinal aquí es 4. Este contenido aparece en cuarto lugar de las 22 secciones de contenido total.

Agregue un select parámetro para limitar los resultados a menos campos. Agregue un filter para restringir aún más la búsqueda.

### Query the index
POST {{baseUrl}}/indexes/sample-markdown-index/docs/search?api-version=2026-04-01  HTTP/1.1
Content-Type: application/json
api-key: {{apiKey}}
  
{
  "search": "Markdown",
  "count": true,
  "select": "title, content, h2_subheader",
  "filter": "h2_subheader eq 'Conclusion'"
}
HTTP/1.1 200 OK
Transfer-Encoding: chunked
Content-Type: application/json; odata.metadata=minimal; odata.streaming=true; charset=utf-8
Content-Encoding: gzip
Vary: Accept-Encoding
Server: Microsoft-IIS/10.0
Strict-Transport-Security: max-age=2592000, max-age=15724800; includeSubDomains
Preference-Applied: odata.include-annotations="*"
OData-Version: 4.0
request-id: a6f9bd46-a064-4e28-818f-ea077618014b
elapsed-time: 35
Date: Fri, 25 Oct 2024 20:36:10 GMT
Connection: close

{
  "@odata.context": "https://<YOUR-SEARCH-SERVICE-NAME>.search.windows.net/indexes('sample-markdown-index')/$metadata#docs(*)",
  "@odata.count": 1,
  "value": [
    {
      "@search.score": 1.1029507,
      "content": "Markdown is a lightweight yet powerful tool for writing documentation. It supports a variety of formatting options while maintaining simplicity and readability.\r\n\r\nThank you for reviewing this example!",
      "title": "Project Documentation",
      "h2_subheader": "Conclusion"
    }
  ]
}

En el caso de los filtros, también puede usar operadores lógicos (y, o no) y operadores de comparación (eq, ne, gt, lt, ge, le). Las comparaciones de cadenas distinguen mayúsculas de minúsculas. Para obtener más información y ejemplos, consulte Creación de una consulta.

Nota

El $filter parámetro solo funciona en campos marcados como filtrables al crear el índice.

Restablecer y volver a ejecutar

Los indexadores se pueden restablecer para borrar el historial de ejecución, lo que permite una nueva ejecución completa. Las siguientes solicitudes restablecen y vuelven a ejecutar el indexador.

### Reset the indexer
POST {{baseUrl}}/indexers/sample-markdown-indexer/reset?api-version=2026-04-01  HTTP/1.1
api-key: {{apiKey}}

### Run the indexer
POST {{baseUrl}}/indexers/sample-markdown-indexer/run?api-version=2026-04-01  HTTP/1.1
api-key: {{apiKey}}

### Check indexer status 
GET {{baseUrl}}/indexers/sample-markdown-indexer/status?api-version=2026-04-01  HTTP/1.1
api-key: {{apiKey}}

Limpieza de recursos

Cuando trabajas en tu propia suscripción, al final de un proyecto, es una buena idea eliminar los recursos que ya no necesitas. Los recursos que quedan en ejecución te pueden costar dinero. Puede eliminar recursos individualmente o eliminar el grupo de recursos para eliminar todo el conjunto de recursos.

Puede usar el portal de Azure para eliminar índices, indexadores y orígenes de datos.

Pasos siguientes

Ahora que está familiarizado con los conceptos básicos de la indexación de blobs de Azure, eche un vistazo más de cerca a la configuración del indexador para los blobs de Markdown en Azure Storage.