Как добавить поиск в приложение: от простых фильтров до полнотекстового поиска
Чтобы добавить поиск в приложение, начните с самого простого работающего варианта: поля поиска, которое вызывает серверный маршрут; маршрут отбирает строки базы, сопоставляя запрос с несколькими колонками, плюс фильтры, например по категории или цене. Когда этого мало — нужны ранжирование по релевантности, учёт словоформ или много записей, — переходите на полнотекстовый поиск вашей базы данных, а к внешнему поисковому сервису прибегайте, только если нужна сильная терпимость к опечаткам или мгновенные результаты на очень больших данных. Что бы вы ни выбрали, поиск обязан учитывать права доступа: пользователи никогда не должны находить записи, которые им не разрешено видеть.
Что значит «поиск» в вашем приложении
Под поиском понимают несколько разных вещей, и большинству приложений нужно больше одной:
- Поиск по ключевым словам: поле для текста — «найти объявления со словом „сад“».
- Фильтры: структурированный выбор — категория, город, диапазон цен, дата, статус.
- Сортировка: сначала новые, сначала дешёвые, сначала самые релевантные.
- Автодополнение: подсказки во время ввода.
- Терпимость к опечаткам: «ресторан» находит «рестроан».
Для каталога, доски вакансий или магазина фильтры часто важнее текстового поля. Решите, что из этого вам действительно нужно, прежде чем выбирать инструмент.
Ваши варианты
| Подход | Как работает | Подходит для | Ограничения |
|---|---|---|---|
| Фильтрация в браузере | Список загружается и фильтруется в JavaScript | Небольших публичных списков (несколько сотен элементов) | Все данные уходят каждому посетителю; медленно на больших списках |
| Сопоставление по шаблону в базе | Серверный запрос вида «имя содержит текст» без учёта регистра | Небольших и средних приложений, админок | Нет ранжирования; может тормозить на больших таблицах; нет учёта словоформ |
| Полнотекстовый поиск базы | Postgres индексирует слова и ранжирует совпадения | Большинства приложений с контентом | Слабо работает с опечатками без нечёткого сравнения |
| Нечёткое сравнение (триграммы) | Postgres сравнивает последовательности символов на схожесть | Имён, коротких полей, терпимости к опечаткам | Нужно расширение и индекс; требует настройки |
| Внешний поисковый сервис | Отдельный сервис индексирует данные (Algolia, Meilisearch, Typesense, Elasticsearch и другие) | Больших каталогов, мгновенного поиска, сильной терпимости к опечаткам | Ещё один сервис, который нужно синхронизировать, оплачивать и защищать |
Если ваши данные уже лежат в Postgres, его встроенный полнотекстовый поиск — сильный компромисс. Он разбивает текст на слова, приводит их к основам (так что «бегущий» находит «бегать»), игнорирует частые служебные слова и может ранжировать результаты по степени совпадения. С правильным индексом он остаётся быстрым на больших таблицах.
Примеры промптов
Простой старт:
Добавь поле поиска и фильтры на страницу объявлений. Поиск должен сопоставлять запрос с заголовком и описанием без учёта регистра. Фильтры: категория (выпадающий список), город (выпадающий список) и максимальная цена. Выполняй поиск на сервере через постраничный API-маршрут, по 20 результатов на страницу. Храни поиск и фильтры в URL, чтобы результатами можно было поделиться и работала кнопка «назад». Покажи понятное пустое состояние, если ничего не найдено.
Переход на полнотекстовый поиск:
Переведи поиск по объявлениям на полнотекстовый поиск Postgres по заголовку (с большим весом) и описанию. Добавь нужный индекс, ранжируй результаты по релевантности и сохрани существующие фильтры и постраничность. Не меняй существующие данные.
Терпимость к опечаткам для имён:
Добавь нечёткое сравнение по названию компании, чтобы небольшие опечатки всё равно находили результаты. Используй схожесть по триграммам, если она доступна, с индексом, и возвращайся к текущему поиску, если нет.
Пошагово
- Составьте список того, что ищут люди. Какие поля (заголовок, описание, теги, название)? Какие фильтры? По возможности спросите нескольких реальных пользователей.
- Начните с сервера. Добавьте API-маршрут, который принимает запрос и фильтры и возвращает одну страницу результатов. Не загружайте всё в браузер.
- Применяйте права доступа в запросе. Если пользователи видят только свои записи или только опубликованные, это условие должно быть в том же запросе, что и поиск.
- Добавьте постраничность с самого начала — номера страниц или «загрузить ещё».
- Храните состояние поиска в URL (например,
?q=garden&city=leeds). Так работают ссылки для шеринга, кнопка «назад» и индексация отфильтрованных страниц поисковиками, если вы этого хотите. - Откладывайте запросы при вводе с задержкой в несколько сотен миллисекунд после окончания набора, чтобы не отправлять запрос на каждый символ.
- Добавьте индексы, когда поймёте, по каким колонкам вы фильтруете и ищете.
- Переходите на более сложное — полнотекстовый поиск, затем нечёткое сравнение, затем внешний сервис — только когда простой шаг не справляется с реальными пользователями.
- Проверьте на реалистичных данных: сотни или тысячи строк, странные символы, пустые запросы, очень длинные запросы, другие языки, если вы их поддерживаете.
Частые ошибки
- Загрузка всей таблицы в браузер. Для 50 элементов это нормально, для 50 000 — мучительно, и это раскрывает каждую запись, включая те, которые пользователь видеть не должен.
- Поиск, который игнорирует права. Поиск — частая утечка: закрытая или черновая запись появляется, потому что в запросе забыли условие «только мои» или «только опубликованные».
- Построение SQL из сырого пользовательского ввода. Всегда используйте параметризованные запросы. ИИ-конструкторы обычно так и делают, но проверьте, не склеиваются ли строки.
- Нет пустого состояния. «Ничего не найдено» с подсказкой (сбросить фильтры, проверить написание) не даёт людям уйти.
- Нет индексов. Поиск на тестовых данных кажется нормальным, а с ростом реальных данных тормозит.
- Сразу переход на поисковый сервис. Тогда приходится хранить вторую копию данных, синхронизировать удаления и защищать ещё один набор ключей — часто без заметной выгоды.
- Забытый мобильный экран. Фильтры должны помещаться на телефоне; обычно лучше работает выдвижная панель фильтров или сворачиваемый блок, чем боковая колонка.
Чек-лист
- Известно, какие поля участвуют в поиске и какие фильтры есть
- Поиск выполняется на сервере и возвращает постраничные результаты
- Запрос соблюдает те же правила доступа, что и остальное приложение
- Пользовательский ввод передаётся как параметры, а не склеивается в SQL
- Состояние поиска хранится в URL
- Ввод с поиском по мере набора откладывается (debounce)
- Колонки, по которым ищут и фильтруют, проиндексированы
- Пустые, безрезультатные и ошибочные состояния понятны
- Проверено на реалистичных объёмах данных и «грязном» вводе
Добавление поиска в Mythex
В приложении на Mythex данные обычно лежат в Postgres-базе проекта, поэтому можно начать с промптов выше: сначала сопоставление по шаблону, а когда нужно ранжирование — полнотекстовый поиск Postgres. Если вам нужен внешний поисковый сервис, используйте собственный аккаунт и ключ, сохраните ключ как секрет проекта и попросите агента индексировать и запрашивать его на сервере, как описано в Integrate any API.
Поиск — основа многих приложений: о том, как он вписывается в продукт, см. как создать сайт-каталог, как создать доску вакансий и как создать маркетплейс.
Вопросы
Какой самый простой способ добавить поиск в приложение?
Если данные лежат в базе, самое простое — серверный маршрут, который отбирает строки по совпадению без учёта регистра по нескольким колонкам. Для небольшого списка, который уже загружен в браузер, фильтрация в браузере ещё проще.
Нужны ли Algolia или Elasticsearch для поиска?
Обычно сначала нет. Полнотекстовый поиск Postgres хорошо справляется с поиском слов, ранжированием и тысячами-миллионами строк. Внешний поисковый сервис стоит того, когда нужна сильная терпимость к опечаткам, мгновенные результаты при вводе по большим данным или тонкая настройка релевантности.
Почему поиск не находит результаты при опечатках?
Простой поиск и стандартный полнотекстовый ищут слова так, как они введены (или их основы), поэтому опечатка мимо. Нужно нечёткое сравнение, например схожесть по триграммам в Postgres, или поисковый сервис с терпимостью к опечаткам.
Поиск должен работать в браузере или на сервере?
На сервере — для всего, что больше небольшого публичного списка. Серверный поиск масштабируется, учитывает права доступа и не отправляет весь набор данных каждому посетителю.