Помимо автодополнения, простой пример которого мы разобрали в этом курсе , ещё одна распространённая функция поисковых приложений — показ исправлений для слов, набранных с ошибкой.
В Manticore Search есть функция для исправления опечаток: она подбирает для слова подходящие варианты из словаря индекса.
Это можно сделать, включив опцию инфиксации. Инфиксация не только позволяет выполнять поиск с подстановочными знаками, но и создаёт n-граммные хэши из проиндексированных слов.
N-граммы (или просто части слов длиной N символов) используются для поиска слов, близких друг к другу (как обычный текст, а не лингвистически). В сочетании с расстоянием Левенштейна между словом-кандидатом и исходным словом это позволяет предлагать подсказки, которые годятся в качестве исправлений слова с ошибкой. Эту функциональность реализуют функции CALL SUGGEST и CALL QSUGGEST (подробнее в документации).
Ниже разберём, как это работает в Manticore Search, а попробовать самостоятельно можно в нашем интерактивном курсе .
Сначала нам следует включить инфиксацию в нашем индексе.
index movies
{
type = plain
path = /var/lib/manticore/data/movies
source = movies
min_infix_len = 3
}
Использование CALL SUGGEST
Когда пользователь выполняет запрос, который не возвращает результатов, возможно, что он опечатался.
Подключимся к Manticore и возьмём пример (обратите внимание на опечатку в слове 'revenge'):
mysql -P9306 -h0
root@didyoumean-b85fb586f-2nvh2:/tutorial# mysql -P9306 -h0
Welcome to the MariaDB monitor. Commands end with ; or g.
Your MySQL connection id is 1
Server version: 3.2.0 e526a014@191017 release
Copyright (c) 2000, 2018, Oracle, MariaDB Corporation Ab and others.
Type 'help;' or 'h' for help. Type 'c' to clear the current input statement.
Возьмём простой пример подсказки для слова:
CALL SUGGEST('rvenge','movies');
MySQL [(none)]> CALL SUGGEST('rvenge','movies');
+---------+----------+------+
| suggest | distance | docs |
+---------+----------+------+
| revenge | 1 | 77 |
| range | 2 | 5 |
| avenger | 2 | 3 |
| avenged | 2 | 1 |
| event | 3 | 9 |
+---------+----------+------+
5 rows in set (0.00 sec)
Вывод содержит 3 столбца: подсказку, вычисленное расстояние Левенштейна и число документов в индексе, где встречается подсказка.
У первой подсказки расстояние до введённого слова равно 1, и это как раз то слово, которое мы ожидали увидеть.
Обычно самый удачный сценарий — когда на минимальном расстоянии есть единственная подсказка: скорее всего, это именно то, что мы ищем.
Но даже на расстоянии 1 подсказок может быть несколько:
CALL SUGGEST('aprentice','movies');
MySQL [(none)]> CALL SUGGEST('aprentice','movies');
+------------+----------+------+
| suggest | distance | docs |
+------------+----------+------+
| apprentice | 1 | 6 |
| prentice | 1 | 1 |
| practice | 3 | 5 |
| argentine | 3 | 1 |
| prestige | 3 | 1 |
+------------+----------+------+
5 rows in set (0.00 sec)
При одинаковом расстоянии подсказки дополнительно сортируются по числу документов.
В этом примере 'apprentice' скорее всего то, что хотел пользователь, так как у него больше попаданий, чем у 'prentice'.
Конечно, если введённое слово есть в индексе, оно будет первой подсказкой с расстоянием 0
CALL SUGGEST('revenge','movies');
MySQL [(none)]> CALL SUGGEST('revenge','movies');
+----------+----------+------+
| suggest | distance | docs |
+----------+----------+------+
| revenge | 0 | 77 |
| reverse | 2 | 2 |
| revelle | 2 | 1 |
| seven | 3 | 11 |
| berenger | 3 | 9 |
+----------+----------+------+
5 rows in set (0.01 sec)
Если нужно больше подсказок, можно добавить параметр limit:
CALL SUGGEST('aprentice','movies', 10 as limit);
MySQL [(none)]> CALL SUGGEST('aprentice','movies', 10 as limit);
+------------+----------+------+
| suggest | distance | docs |
+------------+----------+------+
| apprentice | 1 | 6 |
| prentice | 1 | 1 |
| practice | 3 | 5 |
| argentine | 3 | 1 |
| prestige | 3 | 1 |
| adventure | 4 | 894 |
| lawrence | 4 | 43 |
| laurence | 4 | 10 |
| terence | 4 | 9 |
| prejudice | 4 | 9 |
+------------+----------+------+
10 rows in set (0.00 sec)
Чтобы сузить список подсказок, можно уменьшить максимальное расстояние Левенштейна (по умолчанию 4) и максимальную разницу в длине слов (по умолчанию 3):
CALL SUGGEST('aprentice','movies', 10 as limit,3 as max_edits,2 as delta_len);
MySQL [(none)]> CALL SUGGEST('aprentice','movies', 10 as limit,3 as max_edits,2 as delta_len);
+------------+----------+------+
| suggest | distance | docs |
+------------+----------+------+
| apprentice | 1 | 6 |
| prentice | 1 | 1 |
| practice | 3 | 5 |
| argentine | 3 | 1 |
| prestige | 3 | 1 |
+------------+----------+------+
5 rows in set (0.00 sec)
Для следующего шага нам нужно выйти из клиента MySQL
exit;
MySQL [(none)]> exit;
Bye
Рабочий пример
Простой рабочий пример «Did you mean» можно увидеть в веб-панели нашего интерактивного курса.
PHP-скрипт выводит простую страницу с результатами поиска.
Если по введённой строке ничего не найдено, скрипт проверяет каждое слово с помощью 'CALL SUGGEST' и пытается составить новую строку запроса.
Если по новой строке запроса что-то нашлось, выводятся её результаты.
Скрипт можно просмотреть с помощью cat /html/index.php
root@didyoumean-b85fb586f-2nvh2:/tutorial# cat /html/index.php
Если вам кажется, что чего-то не хватает, попробуйте пройти курс , прочитайте документацию или задайте вопрос в сообществе.

