Примечание.
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Замечание
Эта функция сейчас доступна в общедоступной предварительной версии. Этот предварительный просмотр предоставляется без соглашения об уровне обслуживания и не предназначается для производственных рабочих нагрузок. Некоторые функции могут не поддерживаться или их возможности могут быть ограничены. Для получения дополнительной информации см. Дополнительные условия использования для предварительных версий Microsoft Azure.
В поиске ИИ Azure индексаторы для хранилища BLOB-объектов Azure, файлов Azure и Microsoft OneLake поддерживают markdown режим синтаксического анализа файлов Markdown. Файлы Markdown можно индексировать двумя способами:
- Режим разбора «один ко многим», создание нескольких документов поиска для каждого файла Markdown
- Режим синтаксического анализа один к одному, создание одного документа поиска на файл Markdown
Подсказка
Перейдите к руководству: Поиск данных Markdown из хранилища BLOB Azure после просмотра этой статьи.
Предпосылки
Поддерживаемый источник данных: хранилище BLOB-объектов Azure, хранилище файлов Azure, Microsoft OneLake.
Для OneLake убедитесь, что выполнены все требования индексатора OneLake.
Служба хранилища Azure для индексаторов BLOB-объектов и индексаторов файлов — это стандартный экземпляр с высокой производительностью (версия 2 общего назначения), поддерживающий уровни горячего и холодного доступа.
Параметры режима синтаксического анализа Markdown
Параметры режима синтаксического анализа указываются в определении индексатора при создании или обновлении индексатора.
POST https://[service name].search.windows.net/indexers?api-version=2025-11-01-preview
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"
}
},
}
Индексатор BLOB-объектов предоставляет submode параметр для определения структуры выходных данных документов поиска. Режим синтаксического анализа Markdown предоставляет следующие параметры подрежимов:
| режим парсинга | подрежим | Поиск документа | Description |
|---|---|---|---|
markdown |
oneToMany |
Несколько на блок данных | (по умолчанию) Разбивает Markdown на несколько документов поиска, каждый из которых представляет собой секцию содержимого (не заголовочную) файла Markdown. Вы можете опустить подмод, если только не хотите выполнять синтаксический анализ по одному. |
markdown |
oneToOne |
Один на один блоб | Анализирует Markdown в один документ поиска с разделами, сопоставленными с определенными заголовками в файле Markdown. |
Для режима oneToMany вам следует ознакомиться с индексированием одного BLOB-объекта для создания множества документов поиска, чтобы понять, как индексатор BLOB-объектов обрабатывает разрешение неоднозначности ключа документа для нескольких документов поиска, созданных из одного и того же BLOB-объекта.
В последующих разделах подробно описан каждый подмод. Если вы не знакомы с клиентами и понятиями индексатора, см. статью "Создание индексатора поиска". Кроме того, следует ознакомиться с подробными сведениями о базовой конфигурации индексатора BLOB-объектов, которая здесь не приводится.
Необязательные параметры синтаксического анализа Markdown
Параметры чувствительны к регистру.
| Имя параметра | Допустимые значения | Description |
|---|---|---|
markdownHeaderDepth |
h1
h2
h3
h4
h5
h6(default)
|
Этот параметр определяет самый глубокий уровень заголовка, который учитывается при анализе, что позволяет гибко обрабатывать структуру документов (например, если markdownHeaderDepth задано h1значение , средство синтаксического анализа распознает только заголовки верхнего уровня, начинающиеся с "#", и все заголовки нижнего уровня рассматриваются как обычный текст). Если это значение не указано, по умолчанию используется h6. |
Этот параметр можно изменить после первоначального создания индексатора, однако структура итоговых документов поиска может измениться в зависимости от содержимого Markdown.
Поддерживаемые элементы Markdown
Синтаксический анализ Markdown разделяет только содержимое на основе заголовков. Все остальные элементы, такие как списки, блоки кода, таблицы и т. д., обрабатываются как обычный текст и передаются в поле содержимого.
Пример содержимого Markdown
Для примеров на этой странице используется следующее содержимое Markdown:
# Section 1
Content for section 1.
## Subsection 1.1
Content for subsection 1.1.
# Section 2
Content for section 2.
Используйте режим синтаксического анализа "один ко многим"
Режим синтаксического анализа "один ко многим" преобразует файлы Markdown в несколько документов для поиска, где каждый документ соответствует определенному разделу контента файла Markdown на основе метаданных заголовка в этой части файла. Markdown анализируется по заголовкам и преобразуется в документы поиска, которые содержат следующее содержимое:
content: строка, содержащая необработанный Markdown, найденный в определённой части на основе метаданных заголовка на этом этапе документа.sections: объект, содержащий подфилды для метаданных заголовка до требуемого уровня заголовка. Например, еслиmarkdownHeaderDepthзадано значениеh3, содержит строковые поляh1иh2h3. Эти поля индексируются путем зеркального отображения этой структуры в индексе или сопоставления полей в формате/sections/h1,sections/h2и т. д. Сведения о конфигурациях индекса и индексатора показаны в следующих примерах. Содержимые подполе:-
h1— Строка, содержащая значение заголовка h1. Пустая строка, если она не задана в данный момент в документе. - (Необязательно)
h2— Строка, содержащая значение заголовка h2. Пустая строка, если она не задана в данный момент в документе. - (Необязательно)
h3— Строка, содержащая значение заголовка h3. Пустая строка, если она не задана в данный момент в документе. - (Необязательно)
h4— Строка, содержащая значение заголовка h4. Пустая строка, если она не задана в данный момент в документе. - (Необязательно)
h5— Строка, содержащая значение заголовка h5. Пустая строка, если она не задана в данный момент в документе. - (Необязательно)
h6— Строка, содержащая значение заголовка h6. Пустая строка, если она не задана в данный момент в документе.
-
ordinal_position: целочисленное значение, указывающее положение раздела в иерархии документов. Это поле используется для упорядочивания разделов в первоначальной последовательности, как они отображаются в документе, начиная с позиции 1 и увеличиваясь последовательно для каждого заголовка.
Схема индекса для парсинга "один ко многим"
Пример конфигурации индекса может выглядеть примерно так:
{
"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"
}]
}]
}
Определение индексатора для синтаксического анализа "один ко многим"
Если имена полей и типы данных совпадают, индексатор BLOB-объектов может выводить сопоставление без явного сопоставления полей, присутствующих в запросе, поэтому конфигурация индексатора, соответствующая предоставленной конфигурации индекса, может выглядеть следующим образом:
POST https://[service name].search.windows.net/indexers?api-version=2025-11-01-preview
Content-Type: application/json
api-key: [admin key]
{
"name": "my-markdown-indexer",
"dataSourceName": "my-blob-datasource",
"targetIndexName": "my-target-index",
"parameters": {
"configuration": { "parsingMode": "markdown" }
},
}
Замечание
Явно задавать submode здесь не нужно, так как oneToMany — значение по умолчанию.
Выходные данные индексатора для анализа по схеме "один ко многим"
Этот файл Markdown приведет к трем документам поиска после индексирования из-за трех разделов содержимого. Документ поиска, полученный из первого раздела содержимого предоставленного документа Markdown, будет содержать следующие значения для content, sectionsh1и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
}
}
Сопоставлять поля "один ко многим" в индексе поиска
Сопоставления полей связывают исходное поле с целевым полем в ситуациях, когда имена полей и типы не идентичны. Сопоставления полей также можно использовать для выделения частей документа Markdown и их переноса в поля верхнего уровня документа поиска.
Следующий пример иллюстрирует этот сценарий. Дополнительные сведения о сопоставлениях полей см. в разделе сопоставления полей.
Допустим, что у вас есть индекс поиска со следующими полями: raw_content типа Edm.String, h1_header типа Edm.String и h2_header типа Edm.String. Чтобы сопоставить Markdown с нужной фигурой, используйте следующие сопоставления полей:
"fieldMappings" : [
{ "sourceFieldName" : "/content", "targetFieldName" : "raw_content" },
{ "sourceFieldName" : "/sections/h1", "targetFieldName" : "h1_header" },
{ "sourceFieldName" : "/sections/h2", "targetFieldName" : "h2_header" },
]
Результирующий документ поиска в индексе будет выглядеть следующим образом:
{
{
"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": "",
}
}
Используйте режим синтаксического анализа один к одному
В режиме синтаксического анализа один к одному весь документ Markdown индексируется как один документ поиска, сохраняя иерархию и структуру исходного содержимого. Этот режим наиболее полезен, если файлы для индексирования используют общую структуру, чтобы можно было использовать эту общую структуру в индексе, чтобы сделать соответствующие поля доступными для поиска.
В определении индексатора задайте parsingMode"markdown" и используйте необязательный markdownHeaderDepth параметр, чтобы определить максимальную глубину заголовка для фрагментирования. Если значение не указано, по умолчанию h6 захватывает все возможные глубины заголовков.
Markdown анализируется по заголовкам и преобразуется в документы поиска, которые содержат следующее содержимое:
document_content: содержит полный текст Markdown в виде одной строки. Это поле служит необработанным представлением входного документа.sections: массив объектов, содержащих иерархическое представление разделов в документе Markdown. Каждый раздел представлен как объект в этом массиве и записывает структуру документа в вложенный способ, соответствующий заголовкам и их соответствующему содержимому. Доступ к полям осуществляется через сопоставления полей, ссылаясь на путь, например/sections/content. Объекты в этом массиве имеют следующие свойства:header_level: строка, указывающая уровень заголовка (h1,h2,h3и т. д.) в синтаксисе Markdown. Это поле помогает понять иерархию и структурировать содержимое.header_name: строка, содержащая текст заголовка, как она отображается в документе Markdown. Это поле предоставляет метку или заголовок для раздела.content: строка, содержащая текстовое содержимое, которое сразу же следует за заголовком, вплоть до следующего заголовка. Это поле записывает подробные сведения или описание, связанные с заголовком. Если под заголовком нет содержимого, значение является пустой строкой.ordinal_position: целочисленное значение, указывающее положение раздела в иерархии документов. Это поле используется для упорядочивания разделов в их исходной последовательности, как они отображаются в документе, начиная с первой порядковой позиции и последовательно увеличивая нумерацию для каждого блока содержимого.sections: массив, содержащий объекты, представляющие подразделы, вложенные в текущий раздел. Этот массив следует той же структуре, что и массив верхнего уровняsections, что позволяет представить несколько уровней вложенного содержимого. Каждый объект подраздела также включает свойстваheader_level,header_name,contentиordinal_position, обеспечивая рекурсивную структуру, представляющую иерархию содержимого Markdown.
Ниже приведен пример Markdown, который мы используем для объяснения схем индекса, разработанных вокруг каждого режима синтаксического анализа.
# Section 1
Content for section 1.
## Subsection 1.1
Content for subsection 1.1.
# Section 2
Content for section 2.
Схема индекса для однозначного синтаксического анализа
Если вы не используете сопоставления полей, форма индекса должна отражать форму содержимого Markdown. Учитывая структуру примера Markdown с двумя разделами и одним подразделом, индекс должен выглядеть следующим образом:
{
"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"
}]
}]
}]
}
Определение индексатора для синтаксического анализа
POST https://[service name].search.windows.net/indexers?api-version=2025-11-01-preview
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",
}
}
}
Выходные данные индексатора для анализа один-к-одному
Поскольку мы хотим индексировать Markdown только до глубины h2 ("##"), нам нужны поля, вложенные на глубину 2, чтобы это соответствовало. Эта конфигурация приведет к следующим данным в индексе:
"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": []
}]
}
Как видно, порядковое положение увеличивается в зависимости от расположения содержимого в документе.
Также следует отметить, что если уровни заголовков пропускаются в содержимом, структура результирующего документа отражает заголовки, которые присутствуют в содержимом Markdown, а не обязательно содержат вложенные разделы для h1 последовательного выполнения h6 . Например, когда документ начинается с h2, то первый элемент в массиве разделов верхнего уровня — h2.
Сопоставление полей "один к одному" в индексе поиска
Если вы хотите извлечь поля с пользовательскими именами из документа, можно использовать сопоставления полей для этого. Используя тот же пример Markdown, что и раньше, рассмотрим следующую конфигурацию индекса:
{
"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",
}
]
}
Извлечение определенных полей из синтаксического Markdown обрабатывается аналогично тому, как пути к документу находятся в outputFieldMappings, за исключением того, что путь начинается вместо /sections/documentнего. Например, /sections/0/content будет сопоставляться с содержимым под элементом в позиции 0 в массиве разделов.
Пример строгого варианта использования может выглядеть примерно так: все файлы Markdown имеют заголовок документа в первом, заголовок подраздела в первом h1h2и сводку в содержимом окончательного абзаца под окончательнымh1. Для индексирования этого содержимого можно использовать следующие сопоставления полей:
"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" },
]
Здесь вы можете извлечь только соответствующие фрагменты из этого документа. Чтобы наиболее эффективно использовать эту функцию, документы, которые планируется индексировать, должны совместно использовать одну и ту же иерархическую структуру заголовков.
Результирующий документ поиска в индексе будет выглядеть следующим образом:
{
"content": "Content for section 1.\r\n",
"document_title": "Section 1",
"opening_subsection_title": "Subsection 1.1",
"summary_content": "Content for section 2."
}
Замечание
В этих примерах указывается, как использовать эти режимы синтаксического анализа полностью с сопоставлениями полей или без них, но можно применить оба в одном сценарии, если это соответствует вашим потребностям.
Управление устаревшими документами при повторной индексации Markdown
При использовании режима синтаксического анализа "один ко многим" повторно индексирование измененного файла Markdown может привести к устаревшим или повторяющимся документам, если разделы удаляются. Это поведение относится к режиму "один ко многим" и не применяется к синтаксическому анализу один к одному.
Общие сведения о поведении
Режим синтаксического анализа "один ко многим"
В oneToMany режиме каждый раздел Markdown (на основе заголовков) индексируется как отдельный документ поиска. При повторном индексировании файла:
- Без автоматического удаления: индексатор перезаписывает существующие документы новыми, но не удаляет документы, которые больше не соответствуют содержимому обновленного файла.
- Потенциал для дублирующихся данных: эта проблема возникает только когда удаляется больше разделов, чем вставляется между запусками индексирования. В таких случаях оставшиеся документы из предыдущей версии остаются в индексе, что приводит к устаревшим записям, которые больше не отражают текущее состояние исходного файла.
Режим синтаксического анализа один к одному
В oneToOne режиме весь файл Markdown индексируется как один документ поиска. При повторном индексировании файла:
- Поведение перезаписи: существующий документ полностью заменен новой версией.
- Нет устаревших разделов: когда файл переиндексирован, существующий документ заменяется на обновленную версию, и удаленное содержимое больше не включается. Единственное исключение состоит в том, если изменится путь к файлу или URI объекта BLOB, это может привести к созданию нового документа наряду со старым.
Варианты обходного решения
Чтобы убедиться, что индекс отражает текущее состояние файлов Markdown, рассмотрите один из следующих подходов:
Вариант 1. Обратимое удаление с метаданными
Этот метод использует мягкое удаление для удаления документов, связанных с конкретным блобом. Дополнительные сведения см. в статье об обнаружении изменений и удаления с помощью индексаторов для Azure Storage в Azure AI Search.
Шаги:
- Пометьте блоб как удаленный, установив поле метаданных.
- Пусть индексатор запускается. Он удаляет все документы в индексе, связанном с этим BLOB-объектом.
- Удалите маркер обратимого удаления и переиндексируйте файл.
Вариант 2. Использование API удаления
Перед повторной индексированием измененного файла Markdown явным образом удалите существующие документы, связанные с этим файлом, с помощью API удаления. Вы можете сделать одно из двух:
- Вручную определите отдельные устаревшие документы, определив дубликаты в индексе, которые необходимо удалить. Это может быть выполнимо для небольших, хорошо понятных изменений, но это может занять много времени.
- (Рекомендуется) Удалите все документы, созданные из одного родительского файла перед повторным индексированием, чтобы избежать несоответствий.
Шаги:
Определите идентификатор документов, связанных с файлом. Используйте запрос, например следующий пример, чтобы получить идентификаторы ключей документа (например, ,
idи т. д.) для всех документов,chunk_idпривязанных к конкретному файлу. Заменитеmetadata_storage_pathна соответствующее поле в индексе, которое сопоставляется с путем к файлу или URI объекта BLOB. Это поле должно быть ключом.GET https://[service name].search.windows.net/indexes/[index name]/docs?api-version=2025-05-01-preview 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" }Отправьте запрос на удаление документов с указанными ключами.
POST https://[service name].search.windows.net/indexes/[index name]/docs/index?api-version=2025-05-01-preview Content-Type: application/json api-key: [admin key] { "value": [ { "@search.action": "delete", "id": "aHR0c...jI1" }, { "@search.action": "delete", "id": "aHR0...MQ2" } ] }Переиндексировать обновленный файл.