LoginSignup
7
7

More than 5 years have passed since last update.

ActiveGroongaを使ってみた

Last updated at Posted at 2014-12-21

Rails で Groonga をいい感じに扱える ActiveGroonga というものがあるようなので,2014-12-19 に出た Rails4.2 で試してみた.

2014-12-23 18:18:58 +0900 コメントを受けて内容を修正.ActiveGroonga4.2では全て意図通りに動作する

参考にしたサイト

Rails プロジェクトを作る

名前は active_record-playground とした.
ActiveRecord は使わないので --skip-active-record する.

$ rails new active_groonga_playground --skip-active-record

ActiveGroonga をインストールする

Gemfile に

# Gemfile
gem "activegroonga", require: "active_groonga"

を追加する.

次に

$ bin/bundle insall

する.

ActiveGroonga のライブラリを Rails 起動時に読み込む

# config/application.rb

# require "active_record/railtie"
require "active_groonga/railtie"

Groonga データベースを作成する

$ bin/rake groonga:create

User モデルを作成する

$ bin/rails generate model user name:short_text
$ bin/rake groonga:migrate

指定可能なカラム名は Schema::TableDefinition に書いてあるようだ.

Tweet モデルを作成する

$ bin/rails generate model tweet content:short_text user:reference
$ bin/rake groonga:migrate

検索用テーブルを作成する

$ bin/rails generate migration CreateFullTextSearchIndex

生成された migration ファイルを編集する

# db/groonga/migrate/20141221113954_create_full_text_search_index.rb
class CreateFullTextSearchIndex < ActiveGroonga::Migration
  def up
    create_table("bigram",
                 type: :patricia_trie,
                 key_type: "ShortText",
                 default_tokenizer: "TokenBigram",
                 key_normalize: true) do |table|
      table.index("tweets.content")
    end
  end

  def down
    remove_table("bigram")
  end
end

create_table に渡すオプションは Schema.create_table を参考のこと.

schema を定義したら migrate する.

$ bin/rake groonga:migrate

使ってみる

$ bin/rails console
Loading development environment (Rails 4.2.0)
irb(main):001:0> User.create(name: "北 太郎")
=> #<User id: 1, created_at: 2014-12-23 18:08:07 +0900, name: "北 太郎", updated_at: 2014-12-23 18:08:07 +0900>
irb(main):002:0> User.create(name: "南 花子")
=> #<User id: 2, created_at: 2014-12-23 18:08:22 +0900, name: "南 花子", updated_at: 2014-12-23 18:08:22 +0900>
irb(main):003:0> Tweet.create(user: 1, content: "北風を吹かせます")
=> #<Tweet id: 1, content: "北風を吹かせます", created_at: 2014-12-23 18:08:32 +0900, updated_at: 2014-12-23 18:08:32 +0900, user: #<User id: 1, created_at: 2014-12-23 18:08:07 +0900, name: "北 太郎", updated_at: 2014-12-23 18:08:07 +0900>>
irb(main):004:0> Tweet.create(user: 1, content: "冷たい空気を送ります")
=> #<Tweet id: 2, content: "冷たい空気を送ります", created_at: 2014-12-23 18:08:40 +0900, updated_at: 2014-12-23 18:08:40 +0900, user: #<User id: 1, created_at: 2014-12-23 18:08:07 +0900, name: "北 太郎", updated_at: 2014-12-23 18:08:07 +0900>>
irb(main):005:0> Tweet.create(user: 2, content: "南風を吹かせます")
=> #<Tweet id: 3, content: "南風を吹かせます", created_at: 2014-12-23 18:08:47 +0900, updated_at: 2014-12-23 18:08:47 +0900, user: #<User id: 2, created_at: 2014-12-23 18:08:22 +0900, name: "南 花子", updated_at: 2014-12-23 18:08:22 +0900>>
irb(main):006:0> Tweet.create(user: 1, content: "暖かい空気を送ります")
=> #<Tweet id: 4, content: "暖かい空気を送ります", created_at: 2014-12-23 18:08:54 +0900, updated_at: 2014-12-23 18:08:54 +0900, user: #<User id: 1, created_at: 2014-12-23 18:08:07 +0900, name: "北 太郎", updated_at: 2014-12-23 18:08:07 +0900>>

意図通りに動いていそうだ.

検索してみよう.検索は条件をブロックで指定する.

irb(main):007:0> set = Tweet.select { |record| record.content =~ "空気" }
=> #<ActiveGroonga::ResultSet:0x007ffec6ac7958 @records=#<Groonga::Hash id: <2147483649>, name: (anonymous), path: (temporary), domain: <tweets>, range: (nil), flags: <WITH_SUBREC>, size: <2>, encoding: <:utf8>, default_tokenizer: (nil), token_filters: [], normalizer: (nil)>, @klass=Tweet(content: ShortText, created_at: Time, updated_at: Time, user: users), @groups={}, @expression=#<Groonga::Expression #<expr
  vars:{
    $1:#<record:no_key:tweets id:0(nonexistent)>
  },
  codes:{
    0:<push(), modify:1, value:#<record:no_key:tweets id:0(nonexistent)>>,
    1:<get_value(), modify:2, value:#<column:var_size tweets.content range:ShortText type:scalar compress:none>>,
    2:<push(), modify:0, value:"空気">,
    3:<match(), modify:0, value:(NULL)>
  }
>>, @n_records=2, @default_sort_keys=nil, @default_limit=nil, @n_key_nested=1>
irb(main):008:0> set.each { |e| p e }
#<Tweet id: 2, content: "冷たい空気を送ります", created_at: 2014-12-23 18:08:40 +0900, updated_at: 2014-12-23 18:08:40 +0900, user: #<User id: 1, created_at: 2014-12-23 18:08:07 +0900, name: "北 太郎", updated_at: 2014-12-23 18:08:07 +0900>>
#<Tweet id: 4, content: "暖かい空気を送ります", created_at: 2014-12-23 18:08:54 +0900, updated_at: 2014-12-23 18:08:54 +0900, user: #<User id: 1, created_at: 2014-12-23 18:08:07 +0900, name: "北 太郎", updated_at: 2014-12-23 18:08:07 +0900>>
=> nil

うむ.うまくできている.

7
7
5

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
7