Поиск подстроки подходит для простых запросов, но не находит значение, в котором части многословного запроса разделены другими символами. Например, по запросу 10.125 all он не находит 10.125.123.0/24 - all, хотя оба фрагмента есть в значении.
Умный поиск разбивает многословный запрос на токены и ищет каждый токен отдельно. Поэтому он находит значения, соответствующие запросу.
Функции normalizeSearchValue, tokenizeSearchQuery и createSearchPredicate из @koobiq/components/core реализуют эти принципы. Реализация подключается по желанию и не меняет поведение компонентов по умолчанию. Ее можно добавить в собственную логику фильтрации.
Поиск с учетом регистра считает строки разными из-за различий в регистре, хотя они совпадают по смыслу. При сравнении WORLD, world и World приводятся к одному значению.
Алгоритм удаляет пробелы в начале и конце введенной строки. Внутренние пробелы сохраняются: их удаление или схлопывание может изменить смысл фразы.
Многословный запрос разбивается на независимые токены. Значение считается совпадением, только если в нем найдены все токены.
Порядок токенов не важен. Например, запросы 10.125 all и all 10.125 находят значение 10.125.123.0/24 - all.
Текст в двойных кавычках считается одним токеном. Пробелы внутри него участвуют в сравнении, поэтому запрос в кавычках требует точного совпадения фразы.
Минимальная длина токена не задана. Например, токен a находит all.
Диакритические знаки — это пометки над, под или внутри букв. К ним относятся, например, знаки в é, ü и ç.
Умный поиск отделяет диакритические знаки от базовых букв и сравнивает результат без них. Поэтому значение Café Wi-Fi находится по запросам cafe и café, независимо от того, какой вариант введен.
Пунктуация не удаляется. Символы /, - и . сохраняются, поэтому IP-диапазоны и похожие значения не изменяются.
Подсветка совпадений также должна учитывать свертку диакритических знаков. У функций kbqHighlightBackground и mcHighlight есть аргумент foldDiacritics. Передайте ему значение true, если ключевые слова сопоставлялись со сверткой, например через createSearchPredicate. Тогда запрос cafe подсветит Café.
Какие поля участвуют в поиске, определяет вызывающий код. Это зависит от структуры данных.
Токен считается найденным, если он совпал хотя бы с одним полем. Все токены должны найтись хотя бы в одном из полей:
const matches = createSearchPredicate('10.125 guest');
matches(['10.125.11.0/24', 'guest network']); // true — «10.125» найден в первом поле, «guest» — во втором
matches(['10.125.11.0/24', 'production']); // false — «guest» не найден ни в одном поле
Логика сопоставления определяет, соответствует ли значение запросу, но не ранжирует результаты.
Если результаты нужно упорядочить по релевантности, добавьте отдельный алгоритм ранжирования:
const tokens = tokenizeSearchQuery(query);
options.filter(createSearchPredicate(query)).sort(rankByRelevance(tokens));
Умный поиск не исправляет опечатки. Например, запрос developr не находит developer.
Поиск по расстоянию редактирования — отдельная задача. Для нее лучше использовать специализированную библиотеку нечеткого поиска, чем расширять собственную логику сопоставления.
На страницах компонентов показано, как подключить умный поиск: Autocomplete, Dropdown, Filter bar, Select, Tag autocomplete, Timezone, Tree select.