
By: Kevin Jarrett – CC BY 2.0
目次
Groonga
Groongaのインストール
Mac OSX
rroongaをインストールする前にgroongaをインストールしておいた方がいいみたい.
1 | brew install groonga --with-mecab |
トークナイザーとしてmecabを使いたいときは–with-mecabオプションをつける.
groonga.org/ja/docs/install/mac_os_x.html#id3
トークナイザーの一覧を見たいときには、コマンドラインでtokenizer_list
1 2 | > tokenizer_list [[0,1410302484.30339,0.00520086288452148],[{"name":"TokenMecab"},{"name":"TokenDelimit"},{"name":"TokenUnigram"},{"name":"TokenBigram"},{"name":"TokenTrigram"},{"name":"TokenBigramSplitSymbol"},{"name":"TokenBigramSplitSymbolAlpha"},{"name":"TokenBigramSplitSymbolAlphaDigit"},{"name":"TokenBigramIgnoreBlank"},{"name":"TokenBigramIgnoreBlankSplitSymbol"},{"name":"TokenBigramIgnoreBlankSplitSymbolAlpha"},{"name":"TokenBigramIgnoreBlankSplitSymbolAlphaDigit"},{"name":"TokenDelimitNull"}]] |
rroongaのインストール
ranguba.org/ja/
「全文検索エンジンgroongaを囲む夕べ #1」のRuby枠の資料公開
1 | gem install rroonga |
チュートリアルの開始
ranguba.org/rroonga/ja/file.tutorial.html
1 | irb --simple-prompt -rubygems -rgroonga |
データベースの作成
1 2 | Groonga::Context.default_options = {:encoding => :utf8} Groonga::Database.create(:path => "bookmark.db") |
- ファイルが大量にできるので、どこかtempディレクトリを作成した方がいい.
データベースへの接続
なにかあって、いったんirbを終了した場合はデータベースに再接続する必要がある.
1 | Groonga::Database.new "bookmark.db" |
テーブルの作成
Groongaには4種類のテーブルがあり、ここではハッシュテーブルを作成する.
1 | Groonga::Schema.create_table("Items", :type => :hash) |
作成したテーブルには次のようにアクセスできる.
1 | items = Groonga["Items"] |
レコードの追加
カラムを作る前にレコード作成というと不思議な感じがするけど、ハッシュテーブルのキーを登録できる.
1 2 | items.add("http://en.wikipedia.org/wiki/Ruby") items.add("http://www.ruby-lang.org/") |
カラムの追加
change_tableメソッドにブロックを与える.
titleという名前のText型のデータを持つカラムを作成するには次のとおり.
1 2 3 | Groonga::Schema.change_table("Items") do |table| table.text("title") end |
titleカラムへのアクセスは次のとおり.
1 | title_column = Groonga["Items.title"] |
全文検索用のインデックスを作成する
全文検索用のテーブルを作成する
Groongaでは別テーブルを作ってそこに単語を収納するみたい.
こんどはパトリシアトライというタイプのテーブルを作成する.
1 2 3 4 | Groonga::Schema.create_table("Terms", :type => :patricia_trie, :normalizer => :NormalizerAuto, :default_tokenizer => "TokenBigram") |
Itemsテーブルにインデックスを設定する
titleカラムにインデックスを設定するのは次のとおり.
1 2 3 | Groonga::Schema.change_table("Terms") do |table| table.index("Items.title") end |
サンプルデータをいれてみる
1 2 | items["http://en.wikipedia.org/wiki/Ruby"].title = "Ruby" items["http://www.ruby-lang.org/"].title = "Ruby Programming Language" |
全文検索してみる
selectを使って、Rubyという単語が含まれているか検索するには次のとおり.
1 2 3 | ruby_items = items.select {|record| record.title =~ "Ruby"} ruby_items.collect {|record| record.key.key} |
record.key.keyというのは、recordのキーをたどってItemsのレコードを取得して、Itemsのレコードのkeyを取得している.
これは次のように表現すれば、自動的にkeyをたどってくれる.
1 | ruby_items.collect {|record| record["_key"]} |
関連するテーブル
UserがItemに関してCommentできるようなテーブルを作ってみる.
Usersテーブルの作成
1 2 3 | Groonga::Schema.create_table("Users", :type => :hash) do |table| table.text("name") end |
Commentsテーブルの作成
参照にはreferenceを使い、別名を使うこともできる.
また、time型のカラムを作成することも可能.
1 2 3 4 5 6 | Groonga::Schema.create_table("Comments") do |table| table.reference("item") table.reference("author", "Users") table.text("content") table.time("issued") end |
Commentsテーブルのcontentにインデックスを作成
1 2 3 | Groonga::Schema.change_table("Terms") do |table| table.index("Comments.content") end |
サンプルデータの挿入
ユーザーデータの登録
1 2 3 | users = Groonga["Users"] users.add("alice", :name => "Alice") users.add("bob", :name => "Bob") |
アイテムデータの登録
1 2 | items.add("http://www.ruby-doc.org/", :title => "Ruby-Doc.org: Documenting the Ruby Language") |
コメントデータの登録
1 2 3 4 5 | comments = Groonga["Comments"] comments.add(:item => "http://www.ruby-doc.org/", :author => "alice", :content => "Ruby documents", :issued => Time.parse("2010-11-20T18:01:22+09:00")) |
メソッド化
1 2 3 4 5 6 7 8 9 | @items = items @comments = comments def add_bookmark(url, title, author, content, issued) item = @items[url] || @items.add(url, :title => title) @comments.add(:item => item, :author => author, :content => content, :issued => issued) end |
サンプルデータをさらに追加
1 2 3 4 5 6 7 8 9 10 | add_bookmark("https://rubygems.org/", "RubyGems.org | your community gem host", "alice", "Ruby gems", Time.parse("2010-10-07T14:18:28+09:00")) add_bookmark("http://ranguba.org/", "Fulltext search by Ruby with groonga - Ranguba", "bob", "Ruby groonga fulltextsearch", Time.parse("2010-11-11T12:39:59+09:00")) add_bookmark("http://www.ruby-doc.org/", "ruby-doc", "bob", "ruby documents", Time.parse("2010-07-28T20:46:23+09:00")) |
全文検索その2
Commentsテーブルのcontentを検索
これは同じ
1 2 3 | records = comments.select do |record| record["content"] =~ "Ruby" end |
返りレコードの操作1〜日付順に並べ替え
1 2 3 | records.sort([{:key => "issued", :order => "descending"}]).each do |record| comment = record end |
返りレコードの操作2〜グループ化
1 2 3 | records.group("item").each do |record| item = record.key end |
少し複雑な検索
検索インデックスはItems.titleとComments.contentに貼られているけど、Items.titleの方を10倍のスコアにして、Itemsのスコアはさらに参照しているComments.contentのスコアの合計で重み付けして並び替える.
1 2 3 4 5 6 7 8 9 10 11 12 | ruby_comments = @comments.select {|record| record.content =~ "Ruby"} ruby_items = @items.select do |record| target = record.match_target do |match_record| match_record.title * 10 end target =~ "Ruby" end ruby_items = ruby_comments.group("item").union!(ruby_items) ruby_items.sort([{:key => "_score", :order => "descending"}]).each do |record| p [record.score, record.title] end |