В одном из внутренних проектов нашей команды возникла вроде бы рядовая задача: нужно было сделать удобный выпадающий список для выбора компетенций. Справочник содержал около тысячи длинных строк, каждая из 5–8 слов. Им пользовались менеджеры — живые люди, а не поисковые роботы. И тут начались жалобы: «Ничего не находит», «Я точно знаю, что такая компетенция есть», «Почему так неудобно?».
Мы разобрались и поняли, что классический поиск по подстроке (тот самый LIKE «%…%», который используют по умолчанию) в этом сценарии бессилен. В статье расскажу, как мы заменили его на «человеческий» нечёткий поиск, потратив минимум времени и ни строчки серверного кода.
Корень зла: поиск не прощает ошибок
Представьте, что менеджер хочет добавить компетенцию «Управление проектами в строительстве». Он начинает набирать в поле:
· «проект управление» — пусто.
· «упровление» — пусто.
· «кибер безопасность» — пусто.
Почему так происходит? Обычный поиск ищет точное совпадение символов подряд. Ему всё равно, что слова можно переставить; он не догадывается, что «упровление» — это «управление» с одной перепутанной буквой; и уж точно не прощает забытый Caps Lock. Ожидания пользователя и логика алгоритма расходились полностью.
Справочник был небольшим и полностью загружался на сторону браузера, поэтому серверные поисковые движки типа Elasticsearch были избыточны. Нужно было лёгкое клиентское решение, которое понимает человеческие ошибки.
Fuse.js: чтобы поиск стал умным
Мы остановились на JavaScript-библиотеке Fuse.js. Она весит всего около 15 килобайт и создана именно для такого нечёткого поиска на клиенте. Внедрение заняло меньше часа, а результат превзошёл ожидания.
Библиотека умеет три главные вещи, которые нам были нужны:
1. Игнорирует регистр. «управление» и «Управление» для неё одно и то же.
2. Понимает перестановку слов. Вы можете ввести «менеджмент проект» или «проект менеджмент» — она сама разобьёт запрос на слова и проверит, что все они где-то встречаются в строке справочника. Больше не нужно помнить точную формулировку.
3. Прощает опечатки. Специальный параметр «чувствительности» разрешает небольшие расхождения в буквах. Вы можете ошибиться на одну-две буквы, и нужный вариант всё равно будет найден.
Настройка свелась к выбору разумного баланса: если сделать систему слишком строгой — опечатки останутся проблемой; слишком мягкой — в выдачу попадёт много мусора. Подобрали золотую середину опытным путём на наших данных.
Как это выглядит для пользователя
Теперь менеджер просто начинает печатать так, как ему удобно:
· «проект управление» → показывает «Управление проектами в строительстве».
· «разроботка ПО» → показывает «Разработка программного обеспечения».
· «безопасность кибер» → показывает «Кибербезопасность и защита данных».
Выбранные элементы собираются в виде тегов над полем ввода, а уже добавленные автоматически исключаются из подсказок — никакого дублирования. Поиск происходит мгновенно, даже с нашей тысячей записей.
Техническая сторона без кода
Весь механизм работает прямо в браузере, без обращений к серверу. При загрузке страницы справочник один раз передаётся библиотеке. Когда пользователь вводит текст, вызов функции поиска возвращает наиболее подходящие варианты отсортированными по релевантности. Мы добавили крошечную задержку в долю секунды перед стартом поиска, чтобы не дёргать систему на каждое нажатие клавиши — это сохраняет плавность работы.
Единожды настроив порог нечёткости и включив «расширенный поиск» (он как раз отвечает за токенизацию запроса), мы закрыли потребность на 100%. Ни строчки серверной логики менять не потребовалось.
Результат: довольные менеджеры и спокойный разработчик
После внедрения количество обращений в техподдержку со словами «не могу найти компетенцию» упало до нуля. Пользователи интуитивно находят то, что им нужно, даже если не помнят точного написания или порядка слов. Время, которое они тратили на борьбу с поиском, теперь расходуется на полезную работу.
Мы получили идеальный для нашего масштаба компромисс: мощный инструмент, который не перегружает ни сервер, ни страницу, и при этом реализуется за считанные минуты.
Что стоит держать в уме
· Нечёткий поиск — не телепатия. Иногда при очень грубых опечатках или слишком общих запросах могут проскочить неожиданные совпадения. Это решается аккуратной настройкой той самой чувствительности на ваших реальных данных.
· Если справочник вырастет до многих тысяч записей, быстродействие на клиенте может начать снижаться. Но для большинства бизнес-справочников это не проблема, а при необходимости можно добавить простую предварительную фильтрацию.
Заключение
Fuse.js показал себя именно тем инструментом, который решает реальную человеческую проблему, а не усложняет жизнь разработчику. Пользователи не должны думать о регистре и идеальном написании — интерфейс обязан подстраиваться под них. Мы потратили меньше часа, чтобы заменить раздражающий «поиск по подстроке» на дружелюбный и понимающий подбор, и ни разу об этом не пожалели.
Если ваши поля автодополнения до сих пор работают как строгий фильтр по маске — очень рекомендую присмотреться к такому подходу. Эффект от внедрения вы почувствуете сразу же по обратной связи от пользователей.