> ## Documentation Index
> Fetch the complete documentation index at: https://private-7c7dfe99-fix-nav-issues.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Структура словаря на основе дерева регулярных выражений

> Настройте словарь на основе дерева регулярных выражений для поиска по шаблонам.

export const CloudNotSupportedBadge = () => {
  return <div className="cloudNotSupportedBadge">
            <div className="cloudNotSupportedIcon">
            <svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
                <path strokeWidth="1.5" d="M6.33366 12.6666L12.3739 12.6667C13.6593 12.6667 14.7073 11.6187 14.7073 10.3334C14.7073 9.04804 13.6593 8.00003 12.3739 8.00003C12.3739 8.00003 12.3337 7.66659 12.0003 7.33325M10.667 5.33322C8.00033 2.33325 4.45395 4.78537 4.14195 6.68203C2.55728 6.7627 1.29395 8.06203 1.29395 9.6667C1.29395 11.3234 2.66699 12.6666 4.00033 12.6666" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" />
                <path strokeWidth="1.5" d="M2.66699 14L12.0003 4.66663" stroke="currentColor" strokeLinecap="round" strokeLinejoin="round" />
            </svg>

        </div>
            Not supported in ClickHouse Cloud
        </div>;
};

<div id="overview">
  ## Обзор
</div>

Словарь `regexp_tree` позволяет сопоставлять ключи со значениями на основе иерархии шаблонов регулярных выражений.
Он оптимизирован для поиска по совпадению с шаблоном (например, для классификации строк, таких как user agent, по шаблонам регулярных выражений), а не для точного сопоставления ключей.

<Frame>
  <iframe src="https://www.youtube.com/embed/ESlAhUJMoz8?si=sY2OVm-zcuxlDRaX" title="Введение в словари regexp_tree в ClickHouse" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen />
</Frame>

<div id="use-regular-expression-tree-dictionary-in-clickhouse-open-source">
  ## Использование словаря на основе дерева регулярных выражений с источником YAMLRegExpTree
</div>

В ClickHouse open-source словари на основе дерева регулярных выражений определяются с помощью источника [`YAMLRegExpTree`](/ru/reference/statements/create/dictionary/sources/yamlregexptree), которому передаётся путь к YAML-файлу, содержащему дерево регулярных выражений.

```sql title="Query" theme={null}
CREATE DICTIONARY regexp_dict
(
    regexp String,
    name String,
    version String
)
PRIMARY KEY(regexp)
SOURCE(YAMLRegExpTree(PATH '/var/lib/clickhouse/user_files/regexp_tree.yaml'))
LAYOUT(regexp_tree)
...
```

Источник словаря [`YAMLRegExpTree`](/ru/reference/statements/create/dictionary/sources/yamlregexptree) описывает структуру дерева регулярных выражений. Например:

```yaml theme={null}
- regexp: 'Linux/(\d+[\.\d]*).+tlinux'
  name: 'TencentOS'
  version: '\1'

- regexp: '\d+/tclwebkit(?:\d+[\.\d]*)'
  name: 'Android'
  versions:
    - regexp: '33/tclwebkit'
      version: '13'
    - regexp: '3[12]/tclwebkit'
      version: '12'
    - regexp: '30/tclwebkit'
      version: '11'
    - regexp: '29/tclwebkit'
      version: '10'
```

Эта конфигурация состоит из списка узлов дерева регулярных выражений. Каждый узел имеет следующую структуру:

* **regexp**: регулярное выражение узла.
* **attributes**: список пользовательских атрибутов словаря. В этом примере есть два атрибута: `name` и `version`. Первый узел определяет оба атрибута. Второй узел определяет только атрибут `name`. Атрибут `version` задаётся дочерними узлами второго узла.
  * Значение атрибута может содержать **обратные ссылки**, указывающие на группы захвата в совпавшем регулярном выражении. В примере значение атрибута `version` в первом узле состоит из обратной ссылки `\1` на группу захвата `(\d+[\.\d]*)` в регулярном выражении. Номера обратных ссылок находятся в диапазоне от 1 до 9 и записываются как `$1` или `\1` (для номера 1). При выполнении запроса обратная ссылка заменяется соответствующей совпавшей группой захвата.
* **child nodes**: список дочерних узлов узла дерева регулярных выражений, каждый из которых имеет собственные атрибуты и (потенциально) дочерние узлы. Сопоставление строк выполняется в порядке обхода в глубину. Если строка соответствует узлу regexp, словарь проверяет, соответствует ли она также его дочерним узлам. В этом случае присваиваются атрибуты самого глубокого совпавшего узла. Атрибуты дочернего узла перезаписывают одноимённые атрибуты родительских узлов. Имена дочерних узлов в YAML-файлах могут быть произвольными, например `versions` в приведённом выше примере.

Словарь дерева регулярных выражений поддерживает доступ только с использованием функций `dictGet`, `dictGetOrDefault` и `dictGetAll`. Например:

```sql title="Query" theme={null}
SELECT dictGet('regexp_dict', ('name', 'version'), '31/tclwebkit1024');
```

```text title="Response" theme={null}
┌─dictGet('regexp_dict', ('name', 'version'), '31/tclwebkit1024')─┐
│ ('Android','12')                                                │
└─────────────────────────────────────────────────────────────────┘
```

В этом случае мы сначала сопоставляем регулярное выражение `\d+/tclwebkit(?:\d+[\.\d]*)` со вторым узлом второго уровня.
Затем словарь продолжает поиск в дочерних узлах и обнаруживает, что строка также соответствует `3[12]/tclwebkit`.
В результате значение атрибута `name` равно `Android` (определено на первом уровне), а значение атрибута `version` равно `12` (определено в дочернем узле).

С помощью сложного YAML-файла конфигурации вы можете использовать словарь дерева регулярных выражений как парсер строки user agent.
ClickHouse поддерживает [uap-core](https://github.com/ua-parser/uap-core), и вы можете посмотреть, как его использовать, в функциональном тесте [02504\_regexp\_dictionary\_ua\_parser](https://github.com/ClickHouse/ClickHouse/blob/master/tests/queries/0_stateless/02504_regexp_dictionary_ua_parser.sh)

<div id="collecting-attribute-values">
  ### Сбор значений атрибутов
</div>

Иногда полезно возвращать значения всех совпавших регулярных выражений, а не только значение листового узла. В таких случаях можно использовать специализированную функцию [`dictGetAll`](/ru/reference/functions/regular-functions/ext-dict-functions#dictGetAll). Если у узла есть значение атрибута типа `T`, `dictGetAll` вернёт `Array(T)`, содержащий ноль или более значений.

По умолчанию число совпадений, возвращаемых для каждого ключа, не ограничено. Ограничение можно передать в `dictGetAll` как необязательный четвёртый аргумент. Массив заполняется в *топологическом порядке*: дочерние узлы идут перед родительскими, а узлы одного уровня следуют порядку, заданному в исходном описании.

Пример:

```sql theme={null}
CREATE DICTIONARY regexp_dict
(
    regexp String,
    tag String,
    topological_index Int64,
    captured Nullable(String),
    parent String
)
PRIMARY KEY(regexp)
SOURCE(YAMLRegExpTree(PATH '/var/lib/clickhouse/user_files/regexp_tree.yaml'))
LAYOUT(regexp_tree)
LIFETIME(0)
```

```yaml theme={null}
# /var/lib/clickhouse/user_files/regexp_tree.yaml
- regexp: 'clickhouse\.com'
  tag: 'ClickHouse'
  topological_index: 1
  paths:
    - regexp: 'clickhouse\.com/docs(.*)'
      tag: 'ClickHouse Documentation'
      topological_index: 0
      captured: '\1'
      parent: 'ClickHouse'

- regexp: '/docs(/|$)'
  tag: 'Documentation'
  topological_index: 2

- regexp: 'github.com'
  tag: 'GitHub'
  topological_index: 3
  captured: 'NULL'
```

```sql title="Query" theme={null}
CREATE TABLE urls (url String) ENGINE=MergeTree ORDER BY url;
INSERT INTO urls VALUES ('clickhouse.com'), ('clickhouse.com/docs/en'), ('github.com/clickhouse/tree/master/docs');
SELECT url, dictGetAll('regexp_dict', ('tag', 'topological_index', 'captured', 'parent'), url, 2) FROM urls;
```

```text title="Response" theme={null}
┌─url────────────────────────────────────┬─dictGetAll('regexp_dict', ('tag', 'topological_index', 'captured', 'parent'), url, 2)─┐
│ clickhouse.com                         │ (['ClickHouse'],[1],[],[])                                                            │
│ clickhouse.com/docs/en                 │ (['ClickHouse Documentation','ClickHouse'],[0,1],['/en'],['ClickHouse'])              │
│ github.com/clickhouse/tree/master/docs │ (['Documentation','GitHub'],[2,3],[NULL],[])                                          │
└────────────────────────────────────────┴───────────────────────────────────────────────────────────────────────────────────────┘
```

<div id="matching-modes">
  ### Режимы сопоставления
</div>

Поведение сопоставления с шаблоном можно изменять с помощью некоторых настроек словаря:

* `regexp_dict_flag_case_insensitive`: использовать регистронезависимое сопоставление (по умолчанию `false`). Можно переопределить в отдельных выражениях с помощью `(?i)` и `(?-i)`.
* `regexp_dict_flag_dotall`: разрешить символу `.` соответствовать символам новой строки (по умолчанию `false`).

<div id="use-regular-expression-tree-dictionary-in-clickhouse-cloud">
  ## Использование словаря на основе дерева регулярных выражений в ClickHouse Cloud
</div>

Источник [`YAMLRegExpTree`](/ru/reference/statements/create/dictionary/sources/yamlregexptree) поддерживается в ClickHouse Open Source, но не в ClickHouse Cloud.
Чтобы использовать словари на основе дерева регулярных выражений в ClickHouse Cloud, сначала создайте словарь на основе дерева регулярных выражений из YAML-файла в локальной установке ClickHouse Open Source, затем выгрузите этот словарь в CSV-файл с помощью табличной функции `dictionary` и оператора [INTO OUTFILE](/ru/reference/statements/select/into-outfile).

```sql theme={null}
SELECT * FROM dictionary(regexp_dict) INTO OUTFILE('regexp_dict.csv')
```

Содержимое CSV-файла:

```text theme={null}
1,0,"Linux/(\d+[\.\d]*).+tlinux","['version','name']","['\\1','TencentOS']"
2,0,"(\d+)/tclwebkit(\d+[\.\d]*)","['comment','version','name']","['test $1 and $2','$1','Android']"
3,2,"33/tclwebkit","['version']","['13']"
4,2,"3[12]/tclwebkit","['version']","['12']"
5,2,"3[12]/tclwebkit","['version']","['11']"
6,2,"3[12]/tclwebkit","['version']","['10']"
```

Схема файла дампа:

* `id UInt64`: идентификатор узла RegexpTree.
* `parent_id UInt64`: идентификатор родительского узла.
* `regexp String`: строка регулярного выражения.
* `keys Array(String)`: имена пользовательских атрибутов.
* `values Array(String)`: значения пользовательских атрибутов.

Чтобы создать словарь в ClickHouse Cloud, сначала создайте таблицу `regexp_dictionary_source_table` со структурой, приведённой ниже:

```sql theme={null}
CREATE TABLE regexp_dictionary_source_table
(
    id UInt64,
    parent_id UInt64,
    regexp String,
    keys   Array(String),
    values Array(String)
) ENGINE=Memory;
```

Затем обновите локальный CSV следующим образом:

```bash theme={null}
clickhouse client \
    --host MY_HOST \
    --secure \
    --password MY_PASSWORD \
    --query "
    INSERT INTO regexp_dictionary_source_table
    SELECT * FROM input ('id UInt64, parent_id UInt64, regexp String, keys Array(String), values Array(String)')
    FORMAT CSV" < regexp_dict.csv
```

Подробнее см. в разделе [Вставка локальных файлов](/ru/integrations/connectors/data-ingestion/insert-local-files). После инициализации исходной таблицы мы можем создать RegexpTree на основе исходной таблицы:

```sql theme={null}
CREATE DICTIONARY regexp_dict
(
    regexp String,
    name String,
    version String
PRIMARY KEY(regexp)
SOURCE(CLICKHOUSE(TABLE 'regexp_dictionary_source_table'))
LIFETIME(0)
LAYOUT(regexp_tree);
```
