Предложения по фразам с использованием одного вызова SUGGEST

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

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

Перед введением QSUGGEST, чтобы достичь "Вы имели в виду ...?", необходимо было извлечь слова из словаря индекса и поместить триграммы слов в отдельный индекс. Поиск на основе триграмм входного слова затем выполнялся против этого индекса. В качестве последующего шага, для улучшения качества возвращаемых результатов, рассчитывались расстояния Левенштейна для возвращенных совпадений.
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