⚠️ Эта страница автоматически переведена, и перевод может быть несовершенным.

Suggestions on phrases using a single SUGGEST call

В этой статье мы обсуждаем, как один вызов CALL QSUGGEST может использоваться для исправления фраз в отдельных случаях.

CALL QSUGGEST был введён в последней версии Sphinx 2.x. Эта инструкция позволяет находить близкие совпадения вводимого слова в словаре индекса с включённым инфиксированием. Наиболее распространённый случай использования этой функции — реализация функциональности "Вы имели в виду ...?".

До появления QSUGGEST, для реализации функции "Вы имели в виду ...?" требовалось извлекать слова из словаря индекса и помещать триграммы этих слов в отдельный индекс. Поиск, основанный на trigrams вводимого слова, затем выполнялся по этому индексу. В дальнейшем, для повышения качества результатов, над найденными совпадениями вычислялись Levenshtein distances .
CALL QSUGGEST устраняет это, так как не требует отдельного индекса и также предоставляет вычисление расстояний Левенштейна, избавляя не только от необходимости в дополнительном индексе (который также требовал бы периодического обновления), но и от дополнительного кода, необходимого для реализации функции.

Хотя CALL QSUGGEST позволяет принимать более одного слова на вход, он будет предлагать варианты только для последнего слова, игнорируя остальные. Противоположный механизм — CALL SUGGEST — использует вместо этого первое слово и игнорирует остальные. Если мы хотим выполнять предложения для нескольких слов, первым вариантом является выполнение нескольких вызовов QSUGGEST. Однако могут возникнуть случаи, когда наш ввод представляет собой конкретный термин или таксономию (например, артикулы товаров или метки), состоящие из более чем одного слова, или слово, разбитое на отдельные части (по ошибке пользователя). В таких случаях можно использовать один SQUGGEST.

Как мы уже сказали выше, CALL QSUGGEST основан на триграммах. Если мы пытаемся сопоставлять термины, состоящие из более чем одного слова, мы можем рассматривать существующие пробелы как индексируемые символы, что даст нам единое «слово», с которым может работать QSUGGEST. Например, мы можем заменить пробелы на подчёркивание, которое включено в стандартную charset_table . Чтобы это работало, нам нужно добавить в индекс дополнительную версию этих терминов, где пробелы (или другие неиндексируемые символы) заменены индексируемым символом. Альтернативой может быть просто удаление пробелов, но тогда мы можем получить одинаковый токен для разных терминов.

В этом коротком примере мы используем дамп статей Википедии, где проиндексировали отдельную версию заголовков статей, в которой пробелы заменены подчёркиваниями.

В первом примере мы намеренно ошибёмся в написании имени одного из основных поддерживающих Manticore Search — Craigslist. Неправильные запросы взяты из реальных поисков, которые приходят на наш сайт:


mysql> CALL QSUGGEST('craig_list','wikititles', 1 as non_char);
+--------------+----------+------+
| suggest      | distance | docs |
+--------------+----------+------+
| craigslist   | 1        | 1    |
| craig_first  | 2        | 1    |
| craig_zisk   | 2        | 1    |
| craig_ellis  | 3        | 1    |
| craig_ellis_ | 3        | 1    |
+--------------+----------+------+
5 rows in set (0.09 sec)

mysql> CALL QSUGGEST('crages_list','wikititles', 1 as non_char);
+--------------+----------+------+
| suggest      | distance | docs |
+--------------+----------+------+
| craigslist   | 3        | 1    |
| swadesh_list | 4        | 2    |
| danger_list  | 4        | 1    |
| dean_s_list  | 4        | 1    |
| lrus_list    | 4        | 1    |
+--------------+----------+------+
5 rows in set (0.13 sec)


mysql> CALL QSUGGEST('crag_list','wikititles', 1 as non_char);
+------------+----------+------+
| suggest | distance | docs |
+------------+----------+------+
| craigslist | 2 | 1 |
| craig_zisk | 3 | 1 |
| brad_listi | 3 | 1 |
| army_list | 3 | 1 |
| cratylism | 3 | 1 |
+------------+----------+------+
5 rows in set (0.03 sec)

Обратная ситуация возникает, когда пользователь не вводит пробел между словами, в результате получая одно слово вместо двух.


mysql> CALL QSUGGEST('starwars','wikititles', 1 as non_char);
+------------+----------+------+
| suggest    | distance | docs |
+------------+----------+------+
| star_wars  | 1        | 108  |
| starways   | 1        | 1    |
| star_wars_ | 2        | 8    |
| stakkars   | 2        | 1    |
| stalwart   | 2        | 1    |
+------------+----------+------+
5 rows in set (0.01 sec)

Мы также можем ошибаться в обоих словах:


mysql> CALL QSUGGEST('abaham_lincol','wikititles', 1 as non_char);
+-----------------+----------+------+
| suggest | distance | docs |
+-----------------+----------+------+
| abraham_lincoln | 2 | 1 |
| abraham_sinkov | 4 | 1 |
+-----------------+----------+------+
2 rows in set (0.14 sec)

Поскольку QSUGGEST использует расстояния Левенштейна, порядок слов имеет значение, и проверка терминов в обратном порядке не даст ожидаемых результатов, например:


mysql> CALL QSUGGEST('lincol_abaham','wikititles', 1 as non_char);
+---------------+----------+------+
| suggest | distance | docs |
+---------------+----------+------+
| lincoln_isham | 4 | 1 |
+---------------+----------+------+
1 row in set (0.14 sec)

В этом случае следует использовать вызов QSUGGEST для каждого слова, либо, если термины можно извлечь отдельно от индекса, использовать поиск по триграммам.

Установить Manticore Search

Установить Manticore Search