Пользовательский Normalizer
Пользовательский Normalizer выполняет единообразную предварительную обработку текста. Он не разбивает текст, а обрабатывает его целиком как один токен. Сочетая фильтры символов (char_filter) и фильтры токенов (token_filter), он поддерживает преобразование регистра, нормализацию символов и аналогичные операции. Его обычно используют там, где требуется нормализация без токенизации, например при поиске по ключевым словам.
Различия между Normalizer и Analyzer
| Критерий сравнения | Normalizer | Analyzer |
|---|---|---|
| Разбиение текста | Нет, весь текст представляет собой один токен | Да, текст разбивается на несколько токенов по заданным правилам |
| Типичный сценарий | Точное сопоставление ключевых слов (например, кодов товаров, идентификаторов) | Полнотекстовый поиск (например, по тексту статьи) |
| Часто используемые фильтры | lowercase, ascii_folding и другие | tokenizer + различные фильтры |
Сценарии использования
- Поиск по ключевым словам: поля с кодами товаров, названиями товаров и идентификаторами пользователей, для которых не требуется токенизация, но нужен единый формат.
- Сопоставление без учёта регистра: значения
ProductAиproductaсчитаются одинаковыми. - Нормализация диакритических знаков и специальных символов: преобразование
Caféвcafeпозволяет избежать пропущенных совпадений из-за различий в символах.
Порядок использования
Полный процесс состоит из трёх шагов:
- (Необязательно) Создайте пользовательские
char_filterиtoken_filter. - Создайте пользовательский Normalizer, объединяющий указанные выше фильтры.
- Укажите Normalizer в операторе создания таблицы через свойство инвертированного индекса.
Шаг 1: создание пользовательских фильтров (необязательно)
Если встроенные фильтры не отвечают вашим требованиям, сначала можно создать пользовательские фильтры.
Подробнее о создании
char_filterиtoken_filterсм. в документе Пользовательский Analyzer.
Шаг 2: создание пользовательского Normalizer
CREATE INVERTED INDEX NORMALIZER IF NOT EXISTS x_normalizer
PROPERTIES (
"char_filter" = "x_char_filter", -- Optional, one or more character filters
"token_filter" = "x_filter1, x_filter2" -- Optional, one or more token filters, executed in order
);
Описание параметров
| Параметр | Обязательный | Описание |
|---|---|---|
char_filter | Нет | Имена одного или нескольких фильтров символов, разделённые запятыми |
token_filter | Нет | Имена одного или нескольких фильтров токенов, выполняемых в указанном порядке |
Шаг 3: указание Normalizer в операторе создания таблицы
В свойствах инвертированного индекса используйте normalizer, чтобы указать нужный Normalizer.
CREATE TABLE tbl (
`id` bigint NOT NULL,
`code` text NULL,
INDEX idx_code (`code`) USING INVERTED PROPERTIES("normalizer" = "x_custom_normalizer")
)
...
normalizer и analyzer взаимно исключают друг друга и не могут быть указаны одновременно в одном индексе.
Управление пользовательскими Normalizer
| Операция | Оператор SQL |
|---|---|
| Просмотр | SHOW INVERTED INDEX NORMALIZER; |
| Удаление | DROP INVERTED INDEX NORMALIZER IF EXISTS x_normalizer; |
Полный пример: игнорирование регистра и диакритических знаков
Сценарий: поле с названием товара должно поддерживать точное сопоставление без учёта регистра и диакритических знаков (например, Café-Products и cafe-products считаются одинаковыми значениями).
Шаги реализации:
- Создайте пользовательский фильтр токенов
my_ascii_foldingдля удаления диакритических знаков. - Создайте Normalizer
lowercase_ascii_normalizer, который объединяет встроенный фильтрlowercaseс фильтромmy_ascii_foldingиз предыдущего шага. - Создайте таблицу и примените Normalizer к полю
product_name. - Проверьте результат нормализации с помощью функции
tokenize.
Пример SQL:
-- 1. Create a custom token filter (when specific parameters are needed)
-- Here, create an ascii_folding filter
CREATE INVERTED INDEX TOKEN_FILTER IF NOT EXISTS my_ascii_folding
PROPERTIES
(
"type" = "ascii_folding",
"preserve_original" = "false"
);
-- 2. Create the normalizer
-- Combine lowercase (built-in) and my_ascii_folding
CREATE INVERTED INDEX NORMALIZER IF NOT EXISTS lowercase_ascii_normalizer
PROPERTIES
(
"token_filter" = "lowercase, my_ascii_folding"
);
-- 3. Use the normalizer when creating a table
CREATE TABLE product_table (
`id` bigint NOT NULL,
`product_name` text NULL,
INDEX idx_name (`product_name`) USING INVERTED PROPERTIES("normalizer" = "lowercase_ascii_normalizer")
) ENGINE=OLAP
DUPLICATE KEY(`id`)
DISTRIBUTED BY RANDOM BUCKETS 1
PROPERTIES (
"replication_allocation" = "tag.location.default: 1"
);
-- 4. Verification test
select tokenize('Café-Products', '"normalizer"="lowercase_ascii_normalizer"');
Ожидаемый результат:
[
{"token":"cafe-products"}
]
Как видно из результата, Café-Products обрабатывается как один токен без разбиения; при этом выполняются преобразование в нижний регистр и удаление диакритических знаков.
Ограничения
- Фильтры, имена которых указаны в
char_filterиtoken_filter, должны существовать: быть встроенными или созданными ранее. - Normalizer можно удалить, только если его не использует ни одна таблица.
- Удалить
char_filterилиtoken_filterможно, только если на него не ссылается ни один Normalizer. - После выполнения оператора, задающего пользовательский Normalizer, синхронизация с BE занимает около 10 секунд. К данным, загруженным после этого, Normalizer применяется корректно.
normalizerиanalyzerнельзя указывать одновременно в одном инвертированном индексе.