TUTORIAL.ja.rdoc in groonga-0.0.1 vs TUTORIAL.ja.rdoc in groonga-0.0.2
- old
+ new
@@ -1,9 +1,9 @@
= チュートリアル
このページでは簡単なアプリケーションの作成を通して
-Ruby/groongaの新しいSennaの操作方法を紹介します。
+Ruby/groongaの操作方法を紹介します。
== インストール
Ruby/groongaはRubyGemsでインストールできます。
@@ -48,18 +48,18 @@
り出すことができます。
[Groonga::Array]
配列。主キーの存在しないテーブルです。レコードはIDによって
識別します。
-ここではハッシュテーブルを利用して、+<items>+という名前のテー
+ここではハッシュテーブルを利用して、<tt><items></tt>という名前のテー
ブルを作成します。
>> items = Groonga::Hash.create(:name => "<items>", :persistent => true)
=> #<Groonga::Hash id: <18>, name: <<items>>, path: </tmp/bookmark.db.0000012>, domain: <nil>, range: <nil>, encoding: <:utf8>, size: <0>>
-これで+<items>+という名前のテーブルが作成できました。
+これで<tt><items></tt>という名前のテーブルが作成できました。
テーブルはRubyのHashのように扱えます。
例えば、以下のように+size+でテーブルに登録されているレコード
の件数を取得できます。
@@ -70,91 +70,215 @@
== レコードを追加する
items>テーブルにレコードを追加します。
>> items.add("http://ja.wikipedia.org/wiki/Ruby")
- => #<Groonga::Record:0x7f0ece6aeaf8 @table=#<Groonga::Hash id: <18>, name: <<items>>, path: </tmp/bookmark.db.0000012>, domain: <nil>, range: <nil>, encoding: <:utf8>, size: <1>>, @id=1>
+ => #<Groonga::Record ...>
>> items.add("http://www.ruby-lang.org/")
- => #<Groonga::Record:0x7f0ece6a9fa8 @table=#<Groonga::Hash id: <18>, name: <<items>>, path: </tmp/bookmark.db.0000012>, domain: <nil>, range: <nil>, encoding: <:utf8>, size: <2>>, @id=2>
+ => #<Groonga::Record ...>
件数を確認すると確かに2件増えています。
>> items.size
=> 2
主キーを指定してレコードを取り出す時には以下のようにします。
- >> items["http://ja.wikipedia.org/wiki/Ruby"]
- => #<Groonga::Record:0x7f0ece699ab8 @table=#<Groonga::Hash id: <18>, name: <<items>>, path: </tmp/bookmark.db.0000012>, domain: <nil>, range: <nil>, encoding: <:utf8>, size: <2>>, @id=1>
+ >> items.find("http://ja.wikipedia.org/wiki/Ruby")
+ => #<Groonga::Record ...>
== 全文検索を行う
各itemのタイトル文字列を登録して、全文検索できるようにしてみ
ましょう。
-まず+<items>+テーブルに+title+という名前のカラムを追加します。
+まず<tt><items></tt>テーブルに+title+という名前のカラムを追加します。
- >> title_colum = items.define_column("title", "<text>")
- => #<Groonga::VarSizeColumn id: <19>, name: <<items>.title>, path: (temporary), domain: <#<Groonga::Hash id: <18>, name: <<items>>, path: </tmp/bookmark.db.0000012>, domain: <nil>, range: <nil>, encoding: <:utf8>, size: <2>>>, range: <#<Groonga::Type id: <7>, name: <<text>>, path: (temporary), domain: <nil>, range: <65536>>>>
+ >> title_colum = items.define_column("title", "<text>", :persistent => true)
+ => #<Groonga::VarSizeColumn ...>
2番目の引数は、追加するカラムのデータ型を示しています。
-+<int>+、+<text>+、+<longtext>+等の型が基本型として用意されて
+<tt><int></tt>、<tt><text></tt>、<tt><longtext></tt>等の型が基本型として用意されて
います。
全文検索するためには、文字列を分解して得られる各単語を格納す
るためのテーブルを別途しなければなりません。ここでは<terms>と
いう名前でテーブルを定義します。
>> terms = Groonga::Hash.create(:name => "<terms>",
:key_type => "<shorttext>",
- :persistent => true)
- => #<Groonga::Hash id: <21>, name: <<terms>>, path: </tmp/bookmark.db.0000015>, domain: <#<Groonga::Type id: <6>, name: <<shorttext>>, path: (temporary), domain: <nil>, range: <4096>>>, range: <nil>, encoding: <:utf8>, size: <0>>
+ :persistent => true,
+ :default_tokenizer => "<token:bigram>")
+ => #<Groonga::Hash ...>
-+<items>+テーブルの+title+カラムに対するインデックスを定義し
-ます。
+ここでは、トークナイザとして<tt>:default_tokenzier =>
+"<token:bigram>"</tt> を指定しています。トークナイザとは文字
+列を単語に分解するオブジェクトのことです。デフォルトではトー
+クナイザは指定されていません。全文検索を利用するためにはトー
+クナイザを指定する必要があるので、ここではN-gramの一種である
+バイグラムを指定しています。
- >> title_index_column = terms.define_column("item_title", items,
- :type => "index",
- :with_position => true)
- => #<Groonga::IndexColumn id: <22>, name: <<terms>.item_title>, path: (temporary), domain: <#<Groonga::Hash id: <21>, name: <<terms>>, path: </tmp/bookmark.db.0000015>, domain: <#<Groonga::Type id: <6>, name: <<shorttext>>, path: (temporary), domain: <nil>, range: <4096>>>, range: <nil>, encoding: <:utf8>, size: <0>>>, range: <#<Groonga::Hash id: <18>, name: <<items>>, path: </tmp/bookmark.db.0000012>, domain: <nil>, range: <nil>, encoding: <:utf8>, size: <2>>>>
+N-gramを利用した全文検索では、分解したN文字とその出現位置を利
+用して全文検索を行います。N-gramのNは文字列を何文字毎に分解す
+るかの文字数になります。groongaは1文字で分解するユニグラム、
+2文字のバイグラム、3文字のトリグラムをサポートしています。
-インデックス用カラムに、検索対象の+<items>+テーブルの+title+
-カラムを設定します。
+単語格納用テーブルの準備ができたので、<tt><items></tt>テーブ
+ルの+title+カラムに対するインデックスを定義します。
- >> title_index_column.source = title_column
- => #<Groonga::VarSizeColumn id: <19>, name: <<items>.title>, path: (temporary), domain: <#<Groonga::Hash id: <18>, name: <<items>>, path: </tmp/bookmark.db.0000012>, domain: <nil>, range: <nil>, encoding: <:utf8>, size: <2>>>, range: <#<Groonga::Type id: <7>, name: <<text>>, path: (temporary), domain: <nil>, range: <65536>>>>
+ >> terms.define_index_column("item_title", items,
+ :persistent => true,
+ :source => "<items>.title")
+ => #<Groonga::IndexColumn ...>
-少し違和感を感じるかも知れませんが、+<items>+テーブルのカラムに
-対するインデックスは、 +<terms>+テーブルのカラムとして定義しま
-す。
+少し違和感を感じるかも知れませんが、<tt><items></tt>テーブル
+のカラムに対するインデックスは、<tt><terms></tt>テーブルのカ
+ラムとして定義します。
-+<items>+にレコードが登録されると、その中に含まれる単語に該当
-するレコードが+<terms>+に自動的に追加されるようになります。
+<tt><items></tt>にレコードが登録されると、その中に含まれる単
+語に該当するレコードが<tt><terms></tt>に自動的に追加されるよ
+うになります。
-+<terms>+は、文書に含まれる語彙に相当する、やや特殊なテーブル
-だと言えます。しかし、他のテーブルと同様に語彙テーブルには自
-由にカラムを追加し、単語毎の様々な属性を管理することができま
-す。これはある種の検索処理を行う際には非常に便利に機能します。
+<tt><terms></tt>は、文書に含まれる語彙に相当する、やや特殊な
+テーブルだと言えます。しかし、他のテーブルと同様に語彙テーブ
+ルには自由にカラムを追加し、単語毎の様々な属性を管理すること
+ができます。これはある種の検索処理を行う際には非常に便利に機
+能します。
これでテーブルの定義は完了です。
先ほど登録した各レコードの+title+カラムに値をセットします。
- >> items["http://ja.wikipedia.org/wiki/Ruby"]["title"] = "Ruby"
+ >> items.find("http://ja.wikipedia.org/wiki/Ruby")["title"] = "Ruby"
=> "Ruby"
- >> items["http://www.ruby-lang.org/"]["title"] = "オブジェクトスクリプト言語Ruby"
+ >> items.find("http://www.ruby-lang.org/")["title"] = "オブジェクトスクリプト言語Ruby"
"オブジェクトスクリプト言語Ruby"
以下のようにして検索することができます。
>> title_index_column.saerch("Ruby").collect {|record| record.key.key}
["http://ja.wikipedia.org/wiki/Ruby", "http://www.ruby-lang.org/"]
検索結果はGroonga::Hashで返されます。ハッシュのキーに見つかっ
-た+<items>+のレコードが入っています。上の例ではrecord.keyで
-+<items>+のレコードを取得して、さらにそのキーを指定して
-(record.key.key)で+<items>+のキーを返しています。
+た<tt><items></tt>のレコードが入っています。上の例では
++record.key+で<tt><items></tt>のレコードを取得して、さらにそ
+のキーを指定して(+record.key.key+)で<tt><items></tt>のキー
+を返しています。
== マルチユーザ向けのブックマークアプリケーション
+
+ここまでで作った単機能のアプリケーションをもう少し拡張して、
+複数のユーザが、それぞれにコメントを記入できるブックマークア
+プリケーションにしてみましょう。
+
+まず、ユーザ情報とコメント情報を格納するテーブルを追加して、
+下図のようなテーブル構成にします。
+
+http://qwik.jp/senna/senna2.files/rect4605.png
+
+まず、<tt><users></tt>テーブルを追加します。
+
+ >> users = Groonga::Hash.create(:name => "<users>",
+ :key_type => "<shorttext>")
+ => #<Groonga::Hash ...>
+ >> users.define_column("name", "<text>")
+ => #<Groonga::VarSizeColumn ...>
+
+
+次に、<tt><comments></tt>テーブルを追加します。
+
+ >> comments = Groonga::Hash.create(:name => "<comments>",
+ :key_type => "<shorttext>")
+ => #<Groonga::Hash ...>
+ >> comments.define_column("item", items)
+ => #<Groonga::FixSizeColumn ..>
+ >> comments.define_column("author", users)
+ => #<Groonga::FixSizeColumn ..>
+ >> comments.define_column("content", "<text>")
+ => #<Groonga::VarSizeColumn ..>
+ >> comments.define_column("issued", "<time>")
+ => #<Groonga::FixSizeColumn ..>
+
+<tt><comments></tt>テーブルの+content+カラムを全文検索できる
+ようにインデックスを定義します。
+
+ >> terms.define_index_column("comment_content", comments,
+ :source => "<comments>.content")
+ => #<Groonga::IndexColumn ...>
+
+これでテーブルが定義できました。
+
+続いてユーザを何人か追加します。
+
+ >> users.add("moritan", :name => "モリタン")
+ => #<Groonga::Record ...>
+ >> users.add("taporobo", :name => "タポロボ")
+ => #<Groonga::Record ...>
+
+次に、実際にユーザがブックマークを貼る時の処理を実行してみま
+しょう。
+
+ユーザ+moritan+が、はてなダイアリーのとあるページをブックマーク
+したと想定します。
+
+まず対象のページが<tt><items></tt>テーブルに登録済かどうか調
+べます。
+
+ >> items.find("http://d.hatena.ne.jp/brazil/20050829/1125321936")
+ => nil
+
+未登録なのでまず当該ページを<tt><items></tt>に登録します。
+
+ >> items.add("http://d.hatena.ne.jp/brazil/20050829/1125321936",
+ :title => "[翻訳]JavaScript: 世界で最も誤解されたプログラミング言語")
+ => #<Groonga::Record ...>
+
+次に、登録したitemを+item+カラムの値に指定して
+<tt><comments></tt>にレコードを登録します。
+
+ >> comments.add(:item => "http://d.hatena.ne.jp/brazil/20050829/1125321936",
+ :author => "moritan",
+ :content => "JavaScript LISP",
+ :issued => 1187430026)
+ => #<Groonga::Record ...>
+
+== メソッド化
+
+上記の一連の手続きをメソッドにまとめてみます。
+
+ >> @items = items
+ >> @comments = comments
+ >> def add_bookmark(url, title, author, content, issued)
+ >> item = @items.find(url) || @items.add(url, :title => title)
+ >> @comments.add(:item => item,
+ >> :author => author,
+ >> :content => content,
+ >> :issued => issued)
+ >> end
+
++itmes+と+comments+をインスタンス変数に代入しているのはメソッ
+ド内からでも見えるようにするためです。
+
++add_bookmark+は以下のような手順を実行しています。
+
+ * <tt><items></tt>テーブルに該当ページのレコードがあるかどうか調べる。
+ * レコードがなければ追加する。
+ * <tt><comments></tt>テーブルにレコードを登録する。
+
+作成したメソッドを呼び出していくつかブックマークを登録してみ
+ましょう。
+
+ >> add_bookmark("http://practical-scheme.net/docs/cont-j.html",
+ "なんでも継続", "moritan", "継続 LISP Scheme", 1187568692)
+ => #<Groonga::Record ...>
+ >> add_bookmark("http://d.hatena.ne.jp/higepon/20070815/1187192864",
+ "末尾再帰", "taporobo", "末尾再帰 Scheme LISP", 1187568793)
+ => #<Groonga::Record ...>
+ >> add_bookmark("http://practical-scheme.net/docs/cont-j.html",
+ "なんでも継続", "taporobo", "トランポリン LISP continuation",
+ 1187568692)
+ => #<Groonga::Record ...>
+
+== 全文検索その2
つづく。。。