🔗 Всем привет, продолжаю рассказывать про наших ботов @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, а дальше отдельный воркер:
• читает события пачками
• обновляет счётчики
• записывает историю
В итоге бот отвечает быстро, а статистика обновляется асинхронно.
Post #81
11K



- ❤ 46
- 🔥 12
- 👍 10
- ❤🔥 3
- 🥰 1
- 🤡 1