grn_mini-groonga05



grn_mini-groonga05

0 0


grn_mini-groonga05

groonga05 slide

On Github ongaeshi / grn_mini-groonga05

grn_mini

Groongaのテーブル構築をRubyでもっと簡単に

自己紹介

おんがえし (http://ongaeshi.me/)

  • Groonga(Rroonga)を使って色々作っています
  • Milkode
    • ソースコード検索エンジン
  • Honyomi
    • 電子書籍検索エンジン

色々と作った結果として・・

  • Rroonga便利!超速い!
    • 100万レコード位追加しても高速に検索出来る
    • 他のストレージエンジンのインストールが不要
  • 反面
    • 大変な所も分かってきた

Rroongaの大変な所 - カラム設定

  • Rubyのデータ型に対応するGroongaのカラム型を調べながら適切な型を指定する必要がある
  • どれが正しいのか分かりにくい
  • 他のテーブルやベクター型はどうやって渡す?
schema.create_table("Documents", :type => :hash) do |table|          
  table.string("path")
  table.string("package")
  table.time("timestamp")
  table.string("suffix")
end

Rroongaの大変な所 - インデックス設定

  • 全文検索を行うには別途語彙テーブルを作成する必要がある
  • テーブル種類や正規化指定、トークナイザーなど複雑
schema.create_table("Terms",
        :type => :patricia_trie,
        :key_normalize => true,
        :default_tokenizer => "TokenBigramSplitSymbolAlphaDigit") do |table|
  table.index("documents.path", :with_position => true)
  table.index("documents.package", :with_position => true)
  table.index("documents.suffix", :with_position => true)
end

もっと気軽に

  • 最初は気軽に使いたい
  • 慣れてきたら細かく設定する
  • RubyのArrayやHash位簡単に使いたい

grn_miniを作ってみた

  • https://github.com/ongaeshi/grn_mini
  • Rroongaにテーブル構築を自動化する薄いラッパーを被せたもの
  • 生のRroongaオブジェクトも簡単に取得出来るので安心

インストール

$ gem install grn_mini

使い方

データベースの初期化orロード

  • test.dbが無い時は作成
  • ある時はロード
require 'grn_mini'
GrnMini::create_or_open("test.db")

GrnMini::Arrayの作成

  • テーブル定義不要
array = GrnMini::Array.new

要素の追加

  • 1つ目を追加した時にデータ型を見てカラム種類を決定
  • 文字列への全文検索用インデックスを自動で貼る
array << {text: "aaa", number: 1} # add()も使えます
array << {text: "bbb", number: 2}
array.size #=> 2

要素の参照

  • 注意: インデックスは1から
array[1].text   #=> "aaa"
array[2].number #=> "2"
array[2].attributes #=> {text: "bbb", number: 2}

検索

# textに"aa"を含むものを探す
results = array.select("text:@aa")

# 検索結果を表示
results.each do |record|
  p record.attributes #=> {text: "aaa", number: 1}
end

生のRroongaオブジェクトを得る

  • いざという時に
array.grn  #=> Groonga::Array

Hashの作成

  • 文字列で高速にアクセス出来る
hash = GrnMini::Hash.new

# Add
hash["a"] = {text:"aaa", number:1}
hash["b"] = {text:"bbb", number:2}
hash["c"] = {text:"ccc", number:3}

# Read
hash["b"].text       #=> "bbb"

# Write
hash["b"].text = "BBB"

まとめ

  • GrnMiniを使うとGroongaのArrayやHashをRuby標準と同じ感覚で使える
  • GroongaのArrayやHashは検索速度がとても速い
  • 追加したデータはデータベースファイルに永続化される

応用編

tmpdb

  • 実験的にデータベースを作ってプログラム終了時に削除する
GrnMini::tmpdb do
  array = GrnMini::Array.new
  array << {text: "aaa", number: 1}
  array << {text: "bbb", number: 2}
  array << {text: "ccc", number: 3}

  # 色々と実験…
end
# Delete temporary database

明示的にカラムを指定する

  • setup_columnsを使う
  • テーブル1個なら基本不要
GrnMini::tmpdb do
  array = GrnMini::Array.new

  # ダミーデータを設定する
  array.setup_columns(
    filename: "",
    int:      0,
    float:    0.0,
    time:     Time.new,
    )

  # データの追加
  array << {filename: "a.txt", int: 1, float: 1.5, time: Time.at(1999)}
end

複数テーブルの連携

  • tableを渡し合う
users = GrnMini::Hash.new("Users")
articles = GrnMini::Hash.new("Articles")

users.setup_columns(name: "")
articles.setup_columns(author: users, text: "")

複数テーブルの連携(2)

users["aaa"] = {name: "Mr.A"}
users["bbb"] = {name: "Mr.B"}

articles["aaa:1"] = {author: users["aaa"], text: "111"}
articles["aaa:2"] = {author: users["aaa"], text: "222"}
articles["bbb:1"] = {author: users["bbb"], text: "111"}

複数テーブルの連携(3)

# 著者がMr.Aで本文に'1'を含む記事
articles.select("author.name:Mr.A text:@1")  #=> ["aaa:1"]

もっと知りたい

https://github.com/ongaeshi/grn_mini

  • 複雑な検索
  • レコードの削除
  • ソート
  • グルーピング
  • スニペット
  • ページネーション

grn_miniのメリット

つまりはRroongaの

Rubyのライブラリで取得出来るものだったら何でも全文検索出来る

grn_miniで気軽に全文検索

  • Rubyにはすでに豊富なライブラリがある
  • Twitterのタイムライン
  • GitHubのログ
  • などなど

ありがとうございました