Кратко

В Manticore, начиная с версии 23.0.0, можно настроить поиск так, чтобы запрос 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 camera

  • iphone 5se battery case

  • canon eos 80d body

  • thinkpad x1 carbon

А теперь представьте, что пользователи ищут так:

  • xt850

  • iphone5se

  • eos80d

  • thinkpadx1

С точки зрения пользователя такие запросы, конечно, должны совпадать. Для движка они часто не совпадают, потому что при индексации текст разбивается на отдельные термины.

Обычно поисковые системы решают такое несоответствие одним из четырёх способов:

  • индексация префиксов или инфиксов

  • добавление пользовательских правил нормализации

  • дублирование контента в альтернативные нормализованные поля

  • индексация соседних пар токенов и при необходимости хранение склеенных вариантов

Новые возможности 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.

Ключевая идея проста:

  • находим соседние пары токенов, похожие на названия моделей

  • также сохраняем эти пары в склеенной форме

  • это позволяет запросам вроде xt850iphone5se или thinkpadx1 находить текст с пробелами

Именно для этого важен bigram_delimiter .

Что нужно знать о bigram_delimiter

bigram_index отвечает за то, какие соседние пары попадут в обработку.

bigram_delimiter определяет, в каком виде сохраняются подходящие биграммы:

  • true: только внутренняя форма с разделителем

  • none: только склеенный токен, например galaxy24

  • both: обе формы

Практическую разницу проще всего понять на конкретных запросах:

  • при true Manticore сохраняет только внутреннюю форму биграммы, нужную для оптимизации фраз, но не сохраняет склеенный вариант из пользовательского ввода. Поэтому запрос xt850 не сработает как соответствие для xt 850

  • при none Manticore сохраняет только склеенную форму, поэтому xt850 может найти xt 850, но для таких пар поиск будет опираться только на это склеенное представление

  • при both Manticore сохраняет оба варианта: внутреннее представление биграммы и склеенную форму. Поэтому xt850 может найти xt 850, а стандартное поведение фразового поиска остается на месте

В таком сценарии both обычно выглядит самым безопасным дефолтом: он закрывает проблему, заметную пользователю, и при этом меньше затрагивает привычную работу обычных фразовых запросов и смешанных нагрузок.

Режим 1: second_numeric

bigram_index = second_numeric
bigram_delimiter = both

Этот режим подходит для названий моделей, где второй токен состоит только из цифр.

Такое часто встречается в товарных каталогах:

  • xt 850

  • galaxy 24

  • playstation 5

  • pixel 8

Идея проста: пользователи часто ищут такие модели в склеенном виде — xt850galaxy24 или 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 подходят

  • 5se80d и x1 не подходят

Режим 2: second_has_digit

bigram_index = second_has_digit
bigram_delimiter = both

Этот режим - более гибкий вариант second_numeric.

Он сохраняет пару, когда второй токен содержит хотя бы одну ASCII‑цифру. Поэтому этот режим намного лучше подходит для реальных каталогов товаров, где идентификаторы моделей часто представляют собой смешанные буквенно-цифровые строки:

  • xt 850

  • iphone 5se

  • eos 80d

  • thinkpad 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

Часто это более подходящий вариант для смешанных идентификаторов моделей, потому что в реальных каталогах нередко встречаются формы вроде 5se80d или x1, а не только чисто цифровые суффиксы вроде 24.

Какой режим выбрать

Если вы хотите, чтобы запрос xt850 находил xt 850, проще всего следовать такому правилу:

  • используйте second_numeric, когда второй токен состоит только из цифр

  • используйте second_has_digit, когда второй токен может быть смешанным, например 5se80d или x1

Есть один практический нюанс: в базовом сценарии это сохраняется и при дополнительных настройках обработки текста. xt 850 все равно совпадает с xt850, если включены morphology='stem_en' и wordforms.

Но это не значит, что эти настройки сами нормализуют склеенный запрос. В тестах iphones 5 совпадал с iphones5, но не с iphone5, даже при стемминге или замене iphones -> iphone через wordforms. Коротко: в простом случае xt 850 и xt850 совместимы с morphology и wordforms, но если они для вас важны, отдельно проверьте нужную форму запроса.

Главное

Проблема xt850 на самом деле не в одном конкретном названии продукта. Речь идёт о более широком несоответствии между тем, как пользователи вводят названия моделей, и тем, как поисковые движки разбивают их на токены.

В Manticore, начиная с версии 23.0.0, для этого есть штатное решение: bigram_delimiter вместе с режимами bigram_index, которые учитывают цифры. Обычно это проще, чем дублировать поля или собирать отдельный пайплайн предобработки.

Если ваша основная проблема — производительность поиска фраз, а не сопоставление склеенных названий моделей, см. Как ускорить поиск фраз с помощью bigram_index .