Раздел 40 · Elasticsearch и ELK

Проблема поиска: почему LIKE в SQL не работает

junior~10 мин

без входаВойди, чтобы отмечать прогресс, вести заметки и решать задачи в редакторе. войти

«Гонец» запускает маркетплейс: теперь в приложении можно заказать еду из шестидесяти ресторанов, а в каталоге полторы тысячи блюд. Первое, что делает клиент, открыв каталог, это набирает в строке поиска «пицца с грибами». Разработчики быстро сделали поиск на PostgreSQL, и через день служба поддержки принесла жалобы: «ищу грибы, а он ничего не находит», «написал пица с одной ц, пусто», «нашлось, но первым идёт какой-то суп». Разберёмся, почему простой поиск в базе данных так плохо ищет.

Поиск, которого ждут люди

Вспомни, как ты ищешь в любимом приложении доставки. Ты пишешь как попало: с маленькой буквы, в любом падеже, с опечатками, в любом порядке слов. И ждёшь, что:

  • «грибы» найдут и «с грибами», и «грибной суп»;
  • «пица» найдёт «пиццу», потому что опечатка очевидна;
  • «пицца грибы» найдёт пиццу с грибами, хотя в названии слова стоят в другом порядке и между ними есть «с»;
  • сверху окажется то, что подходит лучше всего, а не то, что добавили в базу первым;
  • ответ придёт мгновенно, даже если блюд миллион.

Это полнотекстовый поиск. А SQL умеет совсем другое.

Что умеет LIKE

Оператор LIKE сравнивает строку с шаблоном: % означает «любые символы». Запрос name LIKE '%пицца%' найдёт строки, где внутри есть ровно такие буквы подряд. Не похожие, а ровно такие. Проверим на маленьком каталоге в настоящем PostgreSQL.

SQL-песочница

База · courier

Загружаю редактор…

База загрузится, когда ты выполнишь запрос или откроешь таблицы.

Выполни запрос, чтобы увидеть результат.

Выполни весь запрос кнопкой или Ctrl/Cmd+Enter. Ctrl+Space открывает подсказки. Можно писать несколько команд через точку с запятой, менять данные и открывать транзакции. У каждой песочницы своя база, изменения живут до ухода со страницы. «Сбросить базу» возвращает учебные данные, но не меняет SQL.

Пусто. В названиях написано «Пицца» с большой буквы, а LIKE различает регистр. Замени LIKE на ILIKE, вариант без учёта регистра из PostgreSQL. Найдутся две пиццы, но не «Мини-пиццы»: там другое окончание. Теперь попробуй ILIKE '%грибы%'. Ни одного блюда, хотя грибов в каталоге четыре: «с грибами», «грибной», «белых грибов». И ILIKE '%пица%' с опечаткой тоже ничего не найдёт.

урок из курса

Урок из курса «Elasticsearch и ELK». Курс покупается один раз и остаётся навсегда: 500 ₽.

Оплата пока не подключена: премиум и курсы открываются промокодом.