注意: 筆者は Rails / PostgreSQL 初心者です。指摘・異論を歓迎します
最近 Wiki のなりそこないのような Rails アプリを作っていて、それに PGroonga を組み込む機会があったので紹介します。
準備 before Rails
開発に使うマシンに Groonga と PGroonga をインストールします。詳しくは Groonga のドキュメント と PGroonga のドキュメント を参照してください。メジャーどころはだいたいサポートされているので、簡単にインストールできると思います。
準備 on Rails
PostgreSQL の PGroonga 拡張を有効にして、インデックスを作成する Rails のマイグレーションを書きます。
以下は、versions
テーブルの body
カラムに PGroonga のインデックスを張る例です:
class EnablePGroonga < ActiveRecord::Migration
def change
enable_extension 'pgroonga'
add_index "versions", ["body"], name: "pgroonga_index", using: :pgroonga
end
end
add_index
メソッドのオプションとして using: :pgroonga
を渡しているのがキモです。
書いたらマイグレーションを実行してください。
検索
Groonga のクエリ記法を使って全文検索する scope は以下のようになります:
class Version < ActiveRecord::Base
scope :full_text_search, ->(query) { where("body @@ ?", query) }
end
これでひとまず検索できるようになりました。
Version.full_text_search "いちご あおい 蘭" # AND 検索
Version.full_text_search "スターライト OR ドリームアカデミー" # OR 検索
Version.full_text_search "いちご -あかり" # NOT 検索: (いちご かつ (あかり を含まない))
scope なので、当然 AR っぽいメソッドチェーンをしてもいい感じになってくれます:
irb(main):001:0> Version.where('created_at > ?', 10.days.ago).full_text_search "いちご"
Version Load (26.5ms) SELECT "versions".* FROM "versions" WHERE (created_at > '2015-05-29 14:42:21.335443') AND (body @@ 'いちご')
クエリ構文を用いない、一つの単語のみによる単純な検索は %%
演算子で実行できます。
class Version < ActiveRecord::Base
scope :one_word_search, ->(query) { where("body %% ?", query) }
end
また、PGroonga は LIKE
演算子もサポートしているので、それを使用しているクエリがあれば自動的に PGroonga での検索に切り替わります (column LIKE %keyword%
と column %% keyword
は等価)。
SQL の演算子についての詳細は PGroonga のドキュメントを参照してください。
おわり
前述したとおり初心者ですがなんなく検索できました。Elastic (旧 Elasticsearch) や Solr のように外部にいろいろ用意したりする必要がなく、またコードへの変更もかなり小さく抑えることができるのでかなり手軽でした (依存 gem は増えません!!!)。
本番環境は internal なものなので紹介はできないのですが、Groonga だけあってとても快適に動いています。