Кратко
С версии 23.0.0 Manticore может делать так, чтобы запрос xt850 находил xt 850, используя
bigram_delimiter
вместе с режимами
bigram_index
, учитывающими цифры.
Это решает типичную проблему токенизации в поиске по товарам: пользователи убирают пробелы из названий моделей, а данные в индексе хранятся как отдельные токены.
Предположения и проверка
В этой статье мы исходим из того, что:
- RT-таблицы созданы по SQL‑примерам ровно в том виде, как они показаны
- используется токенизация по умолчанию, если в примере явно не меняется настройка
- ASCII‑цифры в названиях моделей, поскольку
second_numericиsecond_has_digit— режимы, учитывающие цифры, построенные вокруг0-9
Все SQL‑примеры и ожидаемые результаты в этой статье мы проверили перед публикацией на реальном сервере Manticore 23.0.0, используя новые таблицы, созданные с нуля для каждого сценария.
Проблема не только в xt850
Представьте, что у вас есть каталог с такими товарами:
xt 850 action cameraiphone 5se battery casecanon eos 80d bodythinkpad x1 carbon
А теперь представьте, что пользователи ищут так:
xt850iphone5seeos80dthinkpadx1
Для пользователя такие запросы, конечно, должны совпадать. Для движка они часто не совпадают, потому что при индексации текст разбивается на отдельные термины.
Обычно поисковые системы решают это расхождение одним из четырёх способов:
- индексация префиксов или инфиксов
- добавление пользовательских правил нормализации
- дублирование контента в альтернативные нормализованные поля
- индексация соседних пар токенов и при необходимости хранение склеенных вариантов
Новые возможности работы с биграммами в Manticore — это понятный способ реализовать четвёртый вариант без неудобного дублирования полей.
Базовый случай: почему xt850 не работает по умолчанию
Вот как эта проблема выглядит в самом простом виде:
DROP TABLE IF EXISTS bi_default_demo;
CREATE TABLE bi_default_demo(title text);
INSERT INTO bi_default_demo VALUES
(1,'xt 850 action camera');
SELECT id, title FROM bi_default_demo WHERE MATCH('xt850');
Ожидаемый результат:
Empty set
Почему это не работает?
Потому что при индексации документ разбивается на два отдельных токена, xt и 850, а запрос приходит как один токен, xt850.
По умолчанию Manticore не предполагает, что:
xt850должен быть разбит наxt+850- или
xt+850также должно быть доступно для поиска какxt850
Таким образом, это не проблема работы с опечатками и не проблема фразового поиска. Это несоответствие токенизации: индекс видит два токена, а запрос предоставляет один.
Именно этот разрыв и закрывают новые настройки биграмм. Они позволяют Manticore индексировать выбранные соседние пары токенов в форме, которая также может совпадать со склеенными запросами.
Что здесь дают биграммы
bigram_index
может помочь и с
ускорением фразового поиска
, и с сопоставлением названий моделей, но в этой статье мы сосредотачиваемся на проблеме xt 850 vs xt850.
Ключевая идея проста:
- обнаруживать соседние пары токенов, похожие на названия моделей
- также сохранять эти пары в склеенной форме
- позволять запросам вроде
xt850,iphone5seилиthinkpadx1находить текст с пробелами
Именно здесь важен bigram_delimiter .
Что важно про bigram_delimiter
bigram_index определяет, какие соседние пары подходят.
bigram_delimiter определяет, в каком виде сохраняются подходящие биграммы:
true: только внутренний токен с разделителемnone: только склеенный токен, напримерgalaxy24both: обе формы
Практическую разницу проще всего понять по тому, как это влияет на запросы:
- при
trueManticore сохраняет только внутреннюю форму биграммы для оптимизации фраз, но не сохраняет склеенную форму, которую вводит пользователь, поэтому запросxt850не будет соответствоватьxt 850 - при
noneManticore сохраняет только склеенную форму, так чтоxt850может соответствоватьxt 850, но для таких пар вы целиком опираетесь именно на это склеенное представление - при
bothManticore сохраняет и внутреннее представление биграммы, и склеенную форму, поэтомуxt850может соответствоватьxt 850без отказа от обычного поведения фразового поиска
Для такого сценария both обычно является более безопасным дефолтом, потому что он напрямую решает видимую пользователю проблему и при этом меньше меняет привычное поведение обычных фразовых запросов и смешанных нагрузок.
Режим 1: second_numeric
bigram_index = second_numeric
bigram_delimiter = both
Этот режим рассчитан на названия моделей, где второй токен состоит только из цифр.
Такое часто встречается в товарных каталогах:
xt 850galaxy 24playstation 5pixel 8
Идея проста: пользователи часто ищут такие модели в склеенном виде — xt850, galaxy24 или playstation5, хотя в исходном тексте они записаны с пробелом.
second_numeric сохраняет пару только тогда, когда второй токен состоит исключительно из ASCII‑цифр.
Используйте его, когда:
- у вас есть поколения продуктов и нумерованные модели
- пользователи часто убирают пробелы в поиске
- второй токен обычно состоит только из цифр
Пример
DROP TABLE IF EXISTS bi_second_numeric_demo;
CREATE TABLE bi_second_numeric_demo(title text)
bigram_index='second_numeric'
bigram_delimiter='both';
INSERT INTO bi_second_numeric_demo VALUES
(1,'xt 850 action camera'),
(2,'galaxy 24 ultra'),
(3,'playstation 5 slim'),
(4,'iphone 5se case'),
(5,'canon eos 80d body'),
(6,'thinkpad x1 carbon');
Теперь проверим запросы по одному:
SELECT id, title FROM bi_second_numeric_demo WHERE MATCH('xt850');
+------+----------------------+
| id | title |
+------+----------------------+
| 1 | xt 850 action camera |
+------+----------------------+
SELECT id, title FROM bi_second_numeric_demo WHERE MATCH('galaxy24');
+------+-----------------+
| id | title |
+------+-----------------+
| 2 | galaxy 24 ultra |
+------+-----------------+
SELECT id, title FROM bi_second_numeric_demo WHERE MATCH('playstation5');
+------+--------------------+
| id | title |
+------+--------------------+
| 3 | playstation 5 slim |
+------+--------------------+
SELECT id, title FROM bi_second_numeric_demo WHERE MATCH('iphone5se');
Empty set
SELECT id, title FROM bi_second_numeric_demo WHERE MATCH('eos80d');
Empty set
SELECT id, title FROM bi_second_numeric_demo WHERE MATCH('thinkpadx1');
Empty set
На этом граница режима и проходит:
24и5подходят5se,80dиx1не подходят
Режим 2: second_has_digit
bigram_index = second_has_digit
bigram_delimiter = both
Этот режим — более гибкий вариант second_numeric.
Он сохраняет пару, когда второй токен содержит хотя бы одну ASCII‑цифру. Поэтому этот режим гораздо лучше подходит для реальных каталогов товаров, где идентификаторы моделей часто представляют собой смешанные буквенно-цифровые строки:
xt 850iphone 5seeos 80dthinkpad x1
Используйте его, когда:
- в названиях моделей у вас смешаны буквы и цифры
- пользователи часто удаляют пробелы в своих запросах
- вам нужно удобное для каталога сопоставление, без необходимости индексировать каждую пару в таблице
Пример
DROP TABLE IF EXISTS bi_second_has_digit_demo;
CREATE TABLE bi_second_has_digit_demo(title text)
bigram_index='second_has_digit'
bigram_delimiter='both';
INSERT INTO bi_second_has_digit_demo VALUES
(1,'xt 850 action camera'),
(2,'galaxy 24 ultra'),
(3,'playstation 5 slim'),
(4,'iphone 5se case'),
(5,'canon eos 80d body'),
(6,'thinkpad x1 carbon'),
(7,'kindle paperwhite signature');
Затем проверьте запросы один за другим:
SELECT id, title FROM bi_second_has_digit_demo WHERE MATCH('xt850');
+------+----------------------+
| id | title |
+------+----------------------+
| 1 | xt 850 action camera |
+------+----------------------+
SELECT id, title FROM bi_second_has_digit_demo WHERE MATCH('galaxy24');
+------+-----------------+
| id | title |
+------+-----------------+
| 2 | galaxy 24 ultra |
+------+-----------------+
SELECT id, title FROM bi_second_has_digit_demo WHERE MATCH('iphone5se');
+------+---------------------+
| id | title |
+------+---------------------+
| 4 | iphone 5se case |
+------+---------------------+
SELECT id, title FROM bi_second_has_digit_demo WHERE MATCH('eos80d');
+------+---------------------+
| id | title |
+------+---------------------+
| 5 | canon eos 80d body |
+------+---------------------+
SELECT id, title FROM bi_second_has_digit_demo WHERE MATCH('thinkpadx1');
+------+---------------------+
| id | title |
+------+---------------------+
| 6 | thinkpad x1 carbon |
+------+---------------------+
SELECT id, title FROM bi_second_has_digit_demo WHERE MATCH('kindlesignature');
Empty set
Часто это более подходящий вариант для смешанных идентификаторов моделей, потому что в реальных каталогах нередко встречаются формы вроде 5se, 80d или x1, а не только чисто числовые суффиксы вроде 24.
Какой режим выбрать
Если ваша задача в поиске — именно «Как заставить xt850 находить xt 850?», практическое правило такое:
- используйте
second_numeric, когда второй токен состоит только из цифр - используйте
second_has_digit, когда второй токен может быть смешанным, например5se,80dилиx1
Есть один практический нюанс: в простом случае это совместимо и с другими настройками обработки текста. xt 850 по‑прежнему совпадает с xt850, когда включены morphology='stem_en' и wordforms.
Но это не значит, что эти настройки будут нормализовывать склеенный запрос за вас. В тестах iphones 5 совпадал с iphones5, но не с iphone5, даже при стемминге или замене iphones -> iphone через wordforms. Коротко: в простом случае xt 850 и xt850 совместимы с morphology и wordforms, но если они для вас важны, отдельно проверьте нужную форму запроса.
Главное
Проблема xt850 на самом деле не в одном конкретном названии продукта. Речь идёт о более широком несоответствии между тем, как пользователи вводят названия моделей, и тем, как поисковые движки их токенизируют.
Начиная с версии 23.0.0, Manticore даёт встроенный способ справиться с этим несоответствием: bigram_delimiter плюс режимы bigram_index, учитывающие цифры. Это заметно проще, чем дублировать поля или собирать свои пайплайны предобработки.
Если ваша основная проблема — производительность поиска фраз, а не сопоставление склеенных названий моделей, см. How to Speed Up Phrase Search with bigram_index .
