Pull to refresh

Быстрый полнотекстовый поиск в Rails приложениях

Reading time 3 min
Views 6K
Рано или поздно перед каждым сайтом (будь то социальная сеть, форум, блог или еще какое-то хранилище информации) возникает проблема поиска. Каждый разработчик решает эту проблему по-своему: одни пишут свои решения, другие используют готовые встраиваемые поисковики, третьи используют внешние решения, например сервисы от Google.

В этой статье мне хотелось бы рассказать о таком средстве поиска, как Ferret, и о том, как просто использовать данное решение в своем Rails-приложении.


Итак, ferret — это высокопроизводительный поисковой движок для Ruby, основанный на Apache Lucene. Установка ferret сводится к набору одной единственной команды:

gem install ferret

Ferret — движок, предназначенный для Ruby в целом, а не только для Rails приложений. Использование его в Rails проще чем можно себе представить. Для интеграции Rails и Ferret нужно установить плагин Acts As Ferret в свой проект. Зайдем в папку проекта и в командной строке наберем следующее:

ruby script/plugin install svn://projects.jkraemer.net/acts_as_ferret/tags/stable/acts_as_ferret


Для того чтобы использовать Ferret необходимо сделать следующее: в моделе (предположим, что мы хотим проиндексировать пользователей, а вернее их имя и фамилию), по которой мы хотим производить полнотекстовый поиск добавляем такие строки:

class Member < ActiveRecord::Base
acts_as_ferret :fields => [:first_name, :last_name]
end


После этого Ferret будет индексировать таблицу модели Member. Теперь рассмотрим, как производится поиск.

Самый простой способ — использование метода find_id_by_contents. Итак, если мы напишем следующую иструкцию:

total_results, members = Member.find_id_by_contents("Egor")

То произойдет следующее:
  • создается папка index/development/member, в которую будут помещаться индексы
  • при каждом добавлении, удалении или обновлении участников индексы будут обновляться (без каких либо дополнительных иструкций со стороны разработчика). Если вам по какой-то причине нужно принудительно обновить все индексы, просто удалите папку index/development/member и индексы будут принудительно обновлены
  • ActAsFerret вызовет функцию Search_Each
  • в результате работы функции возвращается общее число найденных записей, а также первые 10 из них в следующем формате

members = [
{:model => "Member", :id => "4", :score => "1.0"},
{:model => "Member", :id => "21", :score => "0.93211"},
{:model => "Member", :id => "27", :score => "0.32212"}
]

Вы можете спросить а что же делать, если хочется получить более 10 результатов? Ответ прост: функция find_id_by_contents имеет несколько параметров, которые позволяют управлять ее поведением:
  • offset — указывает позицию, с которой будет возвращены результаты
  • limit — количество возвращаемых записей


Конечно функцию find_id_by_contents можно использовать с блоком, например так:

results = []
total_results = Member.find_id_by_contents("Egor") {|result|
results.push result
}


Или же, если мы хотим получить записи из базы, а не только идентификаторы, то можно сделать так:

results = []
total_results = Member.find_id_by_contents("Egor") {|result|
results.push Member.find(result[:id])
}


Для решения последней задачи есть более простой способ: использование функции find_by_contents.

@results = Member.find_by_contents("Egor")

Итак, что же делает эта инструкция?
  • вызывает функцию find_id_by_contents для получения идентификаторов
  • достает результаты из базы по найденным идентификаторам
  • возвращает объект класса ActsAsFerret::SearchResults который по сути является небольшой надстройкой над массивом элементов ActiveRecord


Как вы могли заметить использование Ferret достаточно просто и удобно, в то же время, четко вписывается в идеалогию Ruby и Ruby On Rails, поэтому данный инструмент может стать незаменимым помощником для организации поиска в вашем проекте.

P.s. для того, чтобы узнать про такие задачи, связанные с Ferret, как:
  • разбивка результатов поиска на страницы (pagination)
  • продвинутый поиск
  • индексация нестандартных полей
  • сотрировка результатов
  • подстветка результатов поиска
  • установка различных весов для различных полей модели


я рекомендую посмотреть подробнее это руководство (я активно использовал его для написания данной статьи), а также официальный сайт проекта
Tags:
Hubs:
+30
Comments 15
Comments Comments 15

Articles