Post content
🔗 Всем привет, продолжаю рассказывать про наших ботов @sounds и @clips. Сегодня покажу, как работает технология поиска, благодаря которому мы помогаем вам найти максимально релевантные результаты по мемным звукам или кружочкам. Когда вы пишете в боте запрос типа "гойда" или "ну давай нападай", кажется, что это просто "поиск по базе". Но внутри это больше похоже на умный поиск Google, только заточенный под нашу базу (звуки/кружки). 👨💻 Из чего состоит поиск(скриншот 2) У нас есть три слоя, которые работают вместе: • PostgreSQL — основная база, где хранятся сами звуки (название, описание, теги). • Elasticsearch — быстрый “мозг” для полнотекстового поиска (умеет искать по словам, ошибкам, похожим формулировкам). • ZomboDB — магический мост между ними: позволяет делать Elasticsearch-поиск прямо из SQL, как будто это обычный запрос в Postgres. Он также занимается формированием индексов на основе данных Postgres в ElasticSearch. То есть: данные живут в Postgres, а ищем мы силой Elasticsearch, при этом всё выглядит как "одна база". 🐥Что именно мы ищем Каждый звук индексируется по трём главным полям: • title (название) • description (описание) • tags (теги) Они собираются в "единый поисковый документ", и по нему строится индекс. Фишка ZomboDB: когда звук меняется в Postgres — индекс в Elasticsearch обновляется автоматически. Без ручной синхронизации. 📰 Два пути поиска: в боте и через API (скриншот 2) Поиск доступен двумя способами: • Inline в Telegram: @bot <запрос> • Через наш MiniApp, там происходит запрос в API: GET /api/sounds?query=... Но самое главное: оба пути приходят в один и тот же метод — SoundDAO.get_list() (то есть логика поиска единая и вы получите одинаковый результат, независимо от источника взаимодействия). 🙃Как запрос превращается в результат(скриншот 1) Когда вы вводите текст, система делает несколько попыток найти лучшее совпадение. 1) Сначала — "строгий" поиск (MUST) Логика: все слова из запроса должны встретиться. Это даёт максимально точные результаты. И да: поиск умеет "прощать" опечатки — включён режим fuzziness: AUTO, то есть: • «превет» может найти «привет» • «смешной звук» найдёт даже если где-то ошиблись 2) Если строго не нашло — включается "мягкий" поиск (SHOULD) Логика: берём только слова длиннее 3 букв, и достаточно, чтобы совпала примерно половина. Когда полезен: • длинный • с лишними словами • "криво сформулирован" 3) Если и "мягкий" не помог — включается "нечёткий" поиск (FUZZY / SIMILARITY) Логика: мы смотрим на запрос целиком и пытаемся найти похожие варианты, даже если слова написаны по-разному, перепутан порядок или опечаток больше обычного. Это такой режим “ну ты понял, что я имел в виду”. Когда полезен: • короткий и неточный (типа «ааа ну тот звук») • с кучей опечаток / транслитом («privet», «prvyt», «preevet») • с переставленными словами («звук смешной» vs «смешной звук») • когда помнишь только кусок фразы, а остальное “примерно” ⚡️Почему один звук выше другого Результаты сортируются так: • по релевантности (насколько “попали в смысл запроса”) — это score от Elasticsearch • по популярности (сколько раз звук использовали) То есть идеальный вариант — и подходит по смыслу, и реально любимый людьми. 🙈Что происходит, когда вы просто открыли inline и ничего не ввели Если запрос пустой, мы не делаем никакого поиска — вместо этого собираем витрину: • Промо-звуки (сейчас их нет) • Ваша история (последние отправленные) • Топ популярных (по количеству использований) И всё это аккуратно склеивается в один список (до 50 штук), с дедупликацией, чтобы не было повторов. 🚀 Как считаются "использования"(скриншот 3) Когда вы выбираете звук в inline — мы не пишем счётчик сразу в базу (это бы замедлило систему). Вместо этого событие улетает в Redis Stream, а дальше отдельный воркер: • читает события пачками • обновляет счётчики • записывает историю В итоге бот отвечает быстро, а статистика обновляется асинхронно.