Быстрый полнотекстовый поиск в Redmine
У нас используется система управления проектами и задачами Redmine. Мы продолжаем допиливать ее под свои нужды, чтобы повысить удобство работы и расширить функционал. Очередной задачей стало ускорение поиска.
С тех пор как количество задач в Redmine выросло до нескольких сотен тысяч, время на обработку поискового запроса стало занимать десятки секунд, что недопустимо долго для нас. Поэтому мы решили внедрить полнотекстовый поиск на основе Elasticsearch. Про это и будет данный пост.
Описывать, что такое Elasticsearch, для чего он нужен, как его установить и настроить, я не буду. Есть много статей на хабре (например раз, два, три). Остановимся непосредственно на внедрении.
Среди списка плагинов был найден, казалось бы, полностью подходящий redmine_elasticsearch. Но оказалось, не все так просто: этот плагин уже пару лет не поддерживается и сильно устарел (в changelog последняя совместимость указана с Redmine 2.5.x). Однако задача поставлена, и надо ее решать.
Опишу процедуру внедрения
Для работы плагина необходим ряд зависимостей. Во-первых, для выполнения фоновых задач по индексированию сущностей redmine_elasticsearch использует Resque. Но в нашем Redmine несколько плагинов уже использовали Sidekiq для этих задач, и подключать еще Resque не было смысла. Поэтому первым шагом мы заменили Resque на Sidekiq.
Во-вторых, для работы с Elasticsearch используется gem 'tire', который устарел. Более того, все чаще рекомендуется использовать вместо него elasticsearch-rails. Это накладывает жесткое ограничение на версию еластика. Нам удалось добиться работоспособности, но только на версии 1.7.Х. Работу по замене tire мы не проводили и оставили на будущее.
В-третьих, для еластика необходимо два дополнительных плагина:
- Morphological Analysis Plugin for ElasticSearch
- Mapper Attachments Type for Elasticsearch
С их установкой проблем не возникает.
Теперь об установке
Ставится плагин стандартно. Клонируем код из репозитория в папку с плагинами. В нашем случае это выглядит так:
git clone https://github.com/centosadmin/redmine_elasticsearch.git /opt/redmine/plugins
Ставим необходимые гемы:
bundle install
Теперь нужно произвести индексирование всех сущностей Redmine. Это делается командой:
bundle exec rake redmine_elasticsearch:reindex_all RAILS_ENV=production
Обратите внимание: процесс индексирования довольно длительный, в нашем случае он занял ~40 минут.
Стартуем Sidekiq для очереди с именем 'index_queue':
sidekiq -q index_queue
Перезапускаем редмайн.
Все. Плагин готов к работе и заменяет стандартный поиск Redmine на полнотекстовый.
Подведем итог
Мы, конечно, понимаем, что предстоит еще много работы по замене tire на elasticsearch-rails, чтобы устранить жесткую зависимость от версии еластика в будущем. Но найденное решение имеет право на существование и уже доказало свою работоспособность. После внедрения плагина скорость поиска сократилась до ~0.11–0.16 секунды против десятка секунд без него. Мы считаем, это отличный результат. И благодарные отзывы наших сотрудников подтверждают это мнение.
Надеюсь, статья будет вам полезна. Вопросы/замечания и предложения пишите в комментариях. Спасибо за внимание!
Ссылка на форк с нашими доработками: redmine_elasticsearch