Поиск на LIKE-запросах разочаровывает: опечатки не находятся, релевантность случайна, фильтры приходится дописывать вручную. Meilisearch решает задачу отдельным сервисом на Rust: один бинарник, REST API и мгновенная выдача. Разберём установку, индексацию, фильтры, фронтенд, ключи и резервные копии.

Зачем отдельный поисковый движок

Реляционная база умеет искать точные совпадения и подстроки, но не умеет ранжировать результаты по близости слов. Meilisearch строит собственный индекс: разбивает текст на слова, хранит позиции, поддерживает префиксный поиск, опечатки и синонимы. Для сайта с десятками тысяч страниц этого достаточно, а ресурсы несопоставимы с Elasticsearch.

Движок не заменяет базу: он хранит документы в своём индексе, поэтому при изменении статьи её нужно обновить через API. CMS остаётся источником истины.

Установка и запуск

Официальный установщик скачивает бинарник, но для сервера лучше сразу разложить его по системным каталогам и завести отдельного пользователя. Мастер-ключ сгенерируйте заранее и сохраните в файл с правами 600: он даёт полный доступ к API.

curl -L https://install.meilisearch.com | sh
sudo install -m 755 meilisearch /usr/local/bin/meilisearch
sudo useradd --system --home /var/lib/meilisearch --shell /usr/sbin/nologin meilisearch
sudo install -d -o meilisearch -g meilisearch /var/lib/meilisearch/data
openssl rand -hex 32

Параметры задаются переменными окружения. Режим production требует мастер-ключ и запрещает анонимные запросы, адрес 127.0.0.1 оставляет сервис доступным только локально, а аналитику лучше выключить явно.

MEILI_ENV=production
MEILI_HTTP_ADDR=127.0.0.1:7700
MEILI_DB_PATH=/var/lib/meilisearch/data
MEILI_DUMP_DIR=/var/lib/meilisearch/dumps
MEILI_MASTER_KEY=вставьте-ключ-из-openssl
MEILI_NO_ANALYTICS=true

Файл положите в /etc/meilisearch.env и опишите unit для systemd с пользователем meilisearch. Проверка — curl на /health; если сервис не стартует, journalctl покажет занятый порт, права или короткий ключ.

Индексация документов

Индекс создаётся с уникальным полем id. Документы можно отправить массивом JSON или потоком NDJSON, большими партиями. Операции асинхронные: API сразу возвращает uid задачи, а результат нужно смотреть отдельно, иначе ошибка в документе останется незамеченной.

curl -X POST http://127.0.0.1:7700/indexes -H "Authorization: Bearer $MEILI_MASTER_KEY" -H "Content-Type: application/json" --data '{"uid":"pages","primaryKey":"id"}'
curl -X POST http://127.0.0.1:7700/indexes/pages/documents -H "Authorization: Bearer $MEILI_MASTER_KEY" -H "Content-Type: application/json" --data-binary @pages.json
curl -s http://127.0.0.1:7700/tasks -H "Authorization: Bearer $MEILI_MASTER_KEY"
curl -s http://127.0.0.1:7700/indexes/pages/stats -H "Authorization: Bearer $MEILI_MASTER_KEY"

В документ кладут только нужные поля: заголовок, описание, текст, категорию, язык и дату. Пароли и служебные заметки индексировать нельзя. При частых обновлениях скрипт забирает изменения из CMS пакетами, а удалённые страницы убирает через DELETE.

Релевантность, фильтры и сортировка

По умолчанию движок ищет по всем текстовым полям. Настройками можно задать приоритет полей, включить синонимы, стоп-слова и ограничить число результатов. Для фильтров и сортировки поля нужно явно объявить, иначе запрос с filter вернёт ошибку.

curl -X PATCH http://127.0.0.1:7700/indexes/pages/settings -H "Authorization: Bearer $MEILI_MASTER_KEY" -H "Content-Type: application/json" --data '{"searchableAttributes":["title","excerpt","body"],"filterableAttributes":["category","lang"],"sortableAttributes":["date"],"synonyms":{"лмде":["lmde","linux mint debian"]},"pagination":{"maxTotalHits":1000}}'

Порядок правил ранжирования влияет на выдачу. Если точное совпадение должно побеждать популярность, поднимите exactness; для свежести используйте сортировку по дате, не заменяя ею текстовую релевантность. Переиндексация после смены настроек не требуется.

Поиск на сайте

Для фронтенда есть официальный клиент. В браузер попадает только поисковый ключ, мастер-ключ остаётся на сервере. Запрос идёт напрямую к поисковому домену, поэтому настройте CORS и HTTPS.

npm install meilisearch
const client = new MeiliSearch({ host: "https://search.example.com", apiKey: "SEARCH_ONLY_KEY" });
const index = client.index("pages");
const result = await index.search(query, { limit: 10, filter: 'lang = "ru"', attributesToHighlight: ["title"] });

В интерфейсе показывайте заголовок, короткий фрагмент и подсветку совпадений. Не отправляйте запрос на каждое нажатие клавиши без задержки: пауза в 150–250 мс снижает нагрузку и убирает мигание выдачи.

Ключи и безопасность

Мастер-ключ не должен попадать в репозиторий и JavaScript. Для сайта создайте ключ с действием search, ограниченный одним индексом; при утечке его отзывают и выпускают новый.

curl -X POST http://127.0.0.1:7700/keys -H "Authorization: Bearer $MEILI_MASTER_KEY" -H "Content-Type: application/json" --data '{"description":"site search","actions":["search"],"indexes":["pages"],"expiresAt":null}'
curl -s http://127.0.0.1:7700/keys -H "Authorization: Bearer $MEILI_MASTER_KEY"
curl -X DELETE http://127.0.0.1:7700/keys/UID_КЛЮЧА -H "Authorization: Bearer $MEILI_MASTER_KEY"

Если поиск должен учитывать права пользователя, выдавайте не общий ключ, а tenant token с фильтром по доступным документам. Это обязательно для закрытых баз знаний и личных кабинетов.

Резервные копии и обновления

Есть два механизма: дампы и снапшоты. Дамп переносим между версиями и подходит для хранения, снапшот быстрее, но привязан к версии движка. Перед обновлением снимайте дамп, а не только копию каталога данных.

curl -X POST http://127.0.0.1:7700/dumps -H "Authorization: Bearer $MEILI_MASTER_KEY"
curl -X POST http://127.0.0.1:7700/snapshots -H "Authorization: Bearer $MEILI_MASTER_KEY"
ls -lh /var/lib/meilisearch/dumps
meilisearch --import-dump /var/lib/meilisearch/dumps/ДАТА.dump

Восстановление проверяйте отдельно: импортируйте дамп в чистый каталог и сравните число документов. Старый снапшот может не подойти новой версии, дамп решает эту проблему.

Развёртывание за nginx

Порт 7700 не публикуйте напрямую. Поставьте reverse proxy с TLS и ограничьте размер тела запроса. Мастер-ключ передаётся только с сервера, поэтому прокси не должен логировать Authorization.

server {
    listen 443 ssl;
    server_name search.example.com;
    client_max_body_size 100m;
    location / {
        proxy_pass http://127.0.0.1:7700;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

Диагностика

Проверка здоровья, статистики и задач отвечает на большинство вопросов. Если индексация встала, смотрите failed-задачи: обычно причина в неверном типе поля, слишком большом документе или нехватке памяти.

curl -s http://127.0.0.1:7700/health
curl -s http://127.0.0.1:7700/stats -H "Authorization: Bearer $MEILI_MASTER_KEY" | jq
curl -s "http://127.0.0.1:7700/tasks?status=failed" -H "Authorization: Bearer $MEILI_MASTER_KEY" | jq
journalctl -u meilisearch -n 100 --no-pager

Следите за местом: индекс может занимать больше исходных документов. Если поиск замедлился, проверьте число документов, filterableAttributes и лишние индексы; для больших каталогов ограничьте maxTotalHits.

Чек-лист

  • Сервис слушает 127.0.0.1, снаружи доступен только через HTTPS-прокси.
  • Мастер-ключ хранится в файле с правами 600 и не попадает в git.
  • Для фронтенда выпущен отдельный ключ только с действием search.
  • filterableAttributes и sortableAttributes заданы до первых запросов.
  • Скрипт обновления индекса обрабатывает новые, изменённые и удалённые записи.
  • Дамп снимается перед обновлением и проверяется восстановлением.

Итог

Meilisearch добавляет сайту полноценный поиск без кластера и подписки: установка занимает минуты, а настройка сводится к описанию полей и правил ранжирования. Главное — не открывать мастер-ключ наружу и поддерживать индекс в актуальном состоянии. Начните с одного индекса и десяти запросов, проверьте выдачу на реальных материалах, и только потом усложняйте синонимы и фильтры.

Насколько публикация полезна?

Нажмите на звезду, чтобы оценить!

Средняя оценка 0 / 5. Количество оценок: 0

Оценок пока нет. Поставьте оценку первым.

Поделиться: Telegram ВКонтакте