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 つづく。。。