Kouhei Sutou
kou****@clear*****
2012年 8月 27日 (月) 16:09:17 JST
須藤です。 In <CAP4YgqNtHAQOWy3PDia=3ZOqJ****@mail*****> "[groonga-dev,01024] Re: インデックスカラムを参照する方法を教えてください" on Mon, 27 Aug 2012 04:04:16 +0900, okk okk <mikke****@gmail*****> wrote: >> 単語に対応する元文書を参照したいということでしょうか? >> それとも、切り分けられた単語を参照したいということでしょ >> うか?(後者な雰囲気を感じますが。。。) > > > 元文書から切り分けられた単語を参照したい。 > というのがやりたかった事でした。 なるほど。であれば、「単語抽出」という機能を使うとよいと思い ます。単語抽出機能は「文書内から登録済みの単語を抽出する機能」 です。通常は文書内に含まれているキーワードを抽出するためなど に使いますが、「検索対象の文書から語彙表に登録されている単語を 抽出する」、というように使えば、「元文書から切り分けられた単 語を参照」するためにも使えるはずです。 ただし、「単語抽出」機能で抽出すると多めに抽出されます。 (後述) http://groonga.org/ja/docs/reference/grn_expr/script_syntax.html#term-extract-operator まだ、rroongaでは単語抽出機能をRubyっぽく書けないので少し不 恰好ですが、↓でやりたいことができると思います。 require "fileutils" require "groonga" FileUtils.rm_rf("/tmp/db") FileUtils.mkdir_p("/tmp/db") Groonga::Database.create(:path => "/tmp/db/db") Groonga::Schema.define do |schema| schema.create_table("Comments") do |table| table.short_text("content") end schema.create_table("Terms", :type => :patricia_trie, :key_type => :short_text, :key_normalize => true, :default_tokenizer => :token_mecab) do |table| table.index("Comments", "content") end end comments = Groonga["Comments"] terms = Groonga["Terms"] comment = comments.add(:content => "Yes good") comments.add(:content => "Not bad") result_set = terms.select do |record| record.match("_key *T #{comment.content.to_json}", :syntax => :script) end result_set.each do |result| p result.key.key # => "yes" # => "good" end データをこうすると comment = comments.add(:content => "Yes good 東京都知事") comments.add(:content => "Not bad 京都知事") こうなります。 result_set.each do |result| p result.key.key # => "yes" # => "good" # => "d" # => "東京" # => "京都" # => "都知事" # => "知事" end 語彙表に含まれる単語が抽出されるので、複数のデータを登録して いる場合は、データ登録時にMeCabで切り分けた単語以外も抽出さ れます。 注意点は以下の通りです。 * Termsテーブルはパトリシアトライにしないといけない。 * 多めに抽出される。 > 使い道として、キーワードから文書を検索し、その文書から単語を > 抜き出してさらに検索する。という流れを考えていました。 もしかしたら、「類似文書検索」機能も使えるかもしれません。 http://groonga.org/ja/docs/reference/grn_expr/script_syntax.html#similar-search こちらはrroongaも対応しているのでRubyっぽく呼び出せます。 (similar_search(...)) require "fileutils" require "groonga" FileUtils.rm_rf("/tmp/db") FileUtils.mkdir_p("/tmp/db") Groonga::Database.create(:path => "/tmp/db/db") Groonga::Schema.define do |schema| schema.create_table("Comments") do |table| table.short_text("content") end schema.create_table("Terms", :type => :patricia_trie, :key_type => :short_text, :key_normalize => true, :default_tokenizer => :token_mecab) do |table| table.index("Comments", "content") end end comments = Groonga["Comments"] terms = Groonga["Terms"] comments.add(:content => "Yes good") comments.add(:content => "Not bad") comments.add(:content => "Yes bad") result_set = comments.select do |record| record.content.similar_search("OK! Yes!") end result_set.each do |result| p result.key.content # => "Yes good" # => "Yes bad" end 検索対象に完全一致しなくても似ている文書が見つかります。 もし、「単語を抜き出す」という処理を省略してもよいならこの方 法も使えるかもしれません。 > 結果を載せておきます。 > まずはごり押しで"Yes good"の文書から "Yes" と "good"を取りだす。 > result_set = comments.select do |record| > record.content =~ term.key > end.select do |record| > comment.id == record.id > end #一度にクエリを書くやり方が分からなかった。 ここはこんな風に書けます! result_set = comments.select do |record| (record.content =~ term.key) & (record.id == comment.id) end > 正直、これなら mecab を毎回実行したほうが速い気が。。 > なので自前で辞書を作るやり方に変更しました。 > #ベクターで検索出来るはずがでしたが上手くいってません。。 > result = terms.select do |record| > record.inverted_indexes == 1 #失敗。ベクター検索はできない? > end > p result.collect(&:attirbutes) > #[] あぁ、たしかに動かないですねぇ。 ベクターにはいくつか制限があるのです。。。 > また、疑問が出てきた際にはどうかよろしくお願いします。m(_ _)m はい! -- 須藤 功平 <kou****@clear*****> 株式会社クリアコード <http://www.clear-code.com/> (03-6231-7270) groongaサポート: http://groonga.org/ja/support/ パッチ採用はじめました: http://www.clear-code.com/recruitment/