1 March 2011

Полнотекстовый поиск в Grails

Groovy & Grails
Подключить полнотекстовый поиск в Grails — задача довольно легкая. Для этого используется плагин Searchable, который делает все сущности Grails-приложения индексируемыми. Searchable позволяет абстрагировать весь процесс индексирования и поиска. При этом сам плагин использует библиотеку Compass, которая следит за тем, чтобы при изменении объекта (т.е. при сохранении в БД) он автоматически переиндексировался. Сам по себе Compass по сути является довольно мощным средством «поискового ORM»:
  1. Compass на самом низком уровне использует Lucene, но со специальной реализацией индекса.
  2. Compass сопоставляет каждому domain-объекту документ Lucene. Идентификатор объекта при этом становится идентификатором документа.
  3. Поля объекта превращаются в поля документа.
  4. Результатом поиска тоже являются объекты. Их Compass создает (десериализует) на основе данных из индекса.
  5. Compass умеет обрабатывать вложенные объекты (это называется searchable component) и ссылки на объекты (searchable reference). Вложенные объекты будут сохранятся внутри основного документа.
  6. Compass умеет транзакции.
Работать с объектами неизмеримо удобнее; для того, чтобы объявить domain-класс Grails индексируемым, нужно дописать к нему конфигурационный closure такого вида:

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:
  1. Основан на Lucene 3
  2. Изначально проектировался как масштабируемый и доступный (highly available)
  3. Содержит механизмы кэширования (кстати, непохожие на Solr).
Концептуально ElasticSearch довольно сильно отличается от Compass. Фактически ElasticSearch представляет собой индексированное хранилище JSON-объектов. Это хранилище умеет различать разные типы объектов, обрабатывать вложенные объекты и т.п. Ну и самое главное — умеет искать. Язык запросов тоже представляет собой JSON и предоставляет почти такой же набор функций, как и «голый» Lucene.

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 должным образом.
Однако само собой такие вещи не делаются. Что я могу предложить интересующимся? Сейчас в недрах интернета начал развиваться новый Grails-плагин для ElasticSearch. Цели при разработке плагина ставятся такие:
  • Максимальная совместимость с Searchable по настройкам
  • Прозрачность для пользователя (нет необходимости вникать, как работает ElasticSearch)
  • Минимальные требования к пользователю по настройке (установил — запустил).
Плагин уже успешно работает в реальных приложениях. Но нужно больше пользователей и нужен feedback! Нужны люди, которые начнут активно использовать плагин и укажут на проблемы, которые мы сейчас, возможно, не видим.

Где можно взять плагин?Моя ветка, конечно, лучше :-) — там больше функционал и она постоянно прогоняется через наши Grails-приложения с целью вскрыть все проблемы. Периодически мои изменения добавляют в основную ветку, но процесс этот идет с запозданием.

Установить код из Github можно следующим образом:
  1. Предполагаем, что у вас уже есть рабочее Grails-приложение.
  2. Если не хочется возни с git и сборкой, можно поставить уже упакованный плагин:
    grails install-plugin https://github.com/downloads/spn/elasticsearch-grails-plugin/grails-elasticsearch-0.14.2.2.zip
  3. Если хочется собрать самим, это делается чуть сложнее:
    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
    — получим тот же самый упакованный плагин (имя файла из ссылки Downloads в github)
В общем, призываю пробовать. Для информации — плагин сам может работать как текстовое Grails-приложение, просто наберите
grails run-app
в папке с плагином.
Tags:grailssearchablecompasselasticsearchlucene
Hubs: Groovy & Grails
+6
2.9k 11
Leave a comment
Popular right now
Python для веб-разработки
November 27, 202049,500 ₽SkillFactory
Fullstack-разработчик на JavaScript
November 27, 202083,200 ₽SkillFactory
SMM-менеджер
November 27, 202069,900 ₽Нетология
Дизайнер интерфейсов
November 27, 202076,000 ₽GeekBrains
Интернет-маркетолог
November 27, 202074,900 ₽Нетология