33 lines
3.1 KiB
Markdown
33 lines
3.1 KiB
Markdown
# ADR-003: Использование PostgreSQL FTS и pg_trgm вместо Meilisearch/Elasticsearch
|
||
|
||
Дата: 2026-09-06
|
||
Статус: Принято
|
||
|
||
## Контекст
|
||
Для поиска модов по названию, описанию и авторам требуется полнотекстовый поиск и устойчивость к опечаткам (fuzzy search). Введение отдельного движка поиска (Meilisearch, OpenSearch, Elasticsearch) усложняет инфраструктуру и увеличивает потребление RAM (ещё один сервис в `docker-compose`, отдельный индекс, синхронизация).
|
||
|
||
На MVP ожидается <50k модов, поисковый трафик <100 RPS, VPS за $5–10.
|
||
|
||
## Решение
|
||
Использовать возможности PostgreSQL 16:
|
||
- `tsvector` + `GIN`-индексы для ранжированного полнотекстового поиска (`to_tsvector`, `ts_rank`, `plainto_tsquery`).
|
||
- Расширение `pg_trgm` для поиска с опечатками (Trigram Similarity, оператор `%`, `similarity()`).
|
||
- Материализованный `search_vector` с триггером на `INSERT/UPDATE` (см. `docs/database-schema.md`).
|
||
|
||
Запрос: `search_vector @@ plainto_tsquery` + фильтр по `mod_versions` (`GIN (game_versions, loaders)`) + `ORDER BY ts_rank DESC` + fallback `similarity()` при 0 результатах.
|
||
|
||
## Последствия
|
||
|
||
- **Плюсы:** Нет дополнительных сервисов в `docker-compose`, экономия памяти (~0 доп. RAM vs +500MB–1GB у Meilisearch), атомарные транзакции при обновлении индекса (нет лагосинка), проще бэкапы.
|
||
- **Минусы:** При объёме >500k записей или >500 RPS скорость FTS в Postgres начинает уступать специализированным движкам (latency >100ms, нет typo-tolerance из коробки как в Meilisearch).
|
||
- **План миграции:** Если p95 latency поиска превысит 100ms (метрика в `tracing` + Grafana), вынести индекс в Meilisearch: добавить воркер-синк `mods` → Meilisearch, переключить `GET /mods` на Meilisearch с fallback на Postgres. Схема БД не меняется.
|
||
|
||
## Альтернативы (отклонены на MVP)
|
||
|
||
- **Meilisearch** - отличный typo-tolerance, но +1 сервис, нужен отдельный деплой и синк.
|
||
- **Elasticsearch / OpenSearch** - оверхед по RAM/диску, нужен кластер даже для малого объёма.
|
||
- **SQLite FTS** - не подходит, уже Postgres как основной.
|
||
|
||
## Ссылки
|
||
- `docs/database-schema.md` - секция 2 (триггер `mods_search_vector_update`), секция 3 (примеры FTS + fuzzy).
|
||
- `docs/architecture.md` - секция 4 (Поиск без Elasticsearch).
|