Подключить полнотекстовый поиск в Grails — задача довольно легкая. Для этого используется плагин Searchable, который делает все сущности Grails-приложения индексируемыми. Searchable позволяет абстрагировать весь процесс индексирования и поиска. При этом сам плагин использует библиотеку Compass, которая следит за тем, чтобы при изменении объекта (т.е. при сохранении в БД) он автоматически переиндексировался. Сам по себе Compass по сути является довольно мощным средством «поискового ORM»:
Теперь все вновь созданные экземпляры Post будут индексироваться.
В общем-то, больше ничего делать не надо. Можно уже писать поисковые запросы вида:
На самом деле мне не хотелось сейчас пересказывать документацию по Searchable. Есть в нем некие проблемы. Проистекают они из того, что Compass — технически сложный и универсальный продукт, который может использовать как Lucene, так и другие поисковые движки. Поэтому поддерживать весь этот код дальше у его автора нет никакого желания. И его автор, Shay Banon, решил сделать кое-что менее универсальное, но более крутое — поисковую систему ElasticSearch.
ElasticSearch:
Compass — исключительно embedded-решение. Что касается ElasticSearch, то он может существовать и как embedded (внутри JVM) и как HTTP-демон. К демону ElasticSearch может обращаться любая программа, которая знает JSON, будь то PHP-код, Java, Ruby или .NET.
Для тех, кто хочет досконально понять, какой софт тут задействован, я попытался изобразить это на диаграмме:

Здесь видно аж три уровня. Слева изображен текущий стек на основе Compass. Cправа — стек на основе ElasticSearch. Однако распределение функций у Grails-плагинов не совсем одинаковое (например, Compass умеет конвертировать Java-объекты в документы Lucene, а ElasticSearch — нет).
Что теперь светит тем несчастным, которые используют Searchable (а это были и мы в том числе)?
Где можно взять плагин?
Установить код из Github можно следующим образом:
- Compass на самом низком уровне использует Lucene, но со специальной реализацией индекса.
- Compass сопоставляет каждому domain-объекту документ Lucene. Идентификатор объекта при этом становится идентификатором документа.
- Поля объекта превращаются в поля документа.
- Результатом поиска тоже являются объекты. Их Compass создает (десериализует) на основе данных из индекса.
- Compass умеет обрабатывать вложенные объекты (это называется searchable component) и ссылки на объекты (searchable reference). Вложенные объекты будут сохранятся внутри основного документа.
- Compass умеет транзакции.
class Post {
static searchable = {
category index: 'not_analyzed', excludeFromAll: true
title boost: 2.0
comments component: true
}
static hasMany = [comments: Comment]
User author
String title, post, category
Date createdAt
}
Теперь все вновь созданные экземпляры Post будут индексироваться.
В общем-то, больше ничего делать не надо. Можно уже писать поисковые запросы вида:
Post.search("иголка в стоге сена")
и результатом будут сущности вашего приложения! Можно использовать язык запросов Lucene.На самом деле мне не хотелось сейчас пересказывать документацию по Searchable. Есть в нем некие проблемы. Проистекают они из того, что Compass — технически сложный и универсальный продукт, который может использовать как Lucene, так и другие поисковые движки. Поэтому поддерживать весь этот код дальше у его автора нет никакого желания. И его автор, Shay Banon, решил сделать кое-что менее универсальное, но более крутое — поисковую систему ElasticSearch.
ElasticSearch:
- Основан на Lucene 3
- Изначально проектировался как масштабируемый и доступный (highly available)
- Содержит механизмы кэширования (кстати, непохожие на Solr).
Compass — исключительно embedded-решение. Что касается ElasticSearch, то он может существовать и как embedded (внутри JVM) и как HTTP-демон. К демону ElasticSearch может обращаться любая программа, которая знает JSON, будь то PHP-код, Java, Ruby или .NET.
Для тех, кто хочет досконально понять, какой софт тут задействован, я попытался изобразить это на диаграмме:

Здесь видно аж три уровня. Слева изображен текущий стек на основе Compass. Cправа — стек на основе ElasticSearch. Однако распределение функций у Grails-плагинов не совсем одинаковое (например, Compass умеет конвертировать Java-объекты в документы Lucene, а ElasticSearch — нет).
Что теперь светит тем несчастным, которые используют Searchable (а это были и мы в том числе)?
- Searchable больше не развивается. Плагин на диво стабильный, но если что — не ждите багфиксов.
- Compass не развивается. Версии с поддержкой Lucene 3 не будет.
- Нет Lucene 3 — нет большого количества багфиксов и нового функционала. А функционал очень нужен — хотя бы улучшения в морфологии.
- Функционала Searchable уже не хватает;
- Функционал ElasticSearch еще не интегрирован в Grails должным образом.
- Максимальная совместимость с Searchable по настройкам
- Прозрачность для пользователя (нет необходимости вникать, как работает ElasticSearch)
- Минимальные требования к пользователю по настройке (установил — запустил).
Где можно взять плагин?
- Стабильную версию — в репозитории Grails:
grails install-plugin elasticsearch
- Основная ветка плагина — автор Manuarii Stein
- Моя ветка плагина
Установить код из Github можно следующим образом:
- Предполагаем, что у вас уже есть рабочее Grails-приложение.
- Если не хочется возни с git и сборкой, можно поставить уже упакованный плагин:
grails install-plugin https://github.com/downloads/spn/elasticsearch-grails-plugin/grails-elasticsearch-0.14.2.2.zip
- Если хочется собрать самим, это делается чуть сложнее:
— получим тот же самый упакованный плагин (имя файла из ссылки Downloads в github)wget https://github.com/spn/elasticsearch-grails-plugin/tarball/master tar xvzf spn-elasticsearch-grails-plugin-3fde6c4.tar.gz cd spn-elasticsearch-grails-plugin-3fde6c4 grails package-plugin
grails run-app
в папке с плагином.