[groonga-dev,01025] Re: インデックスカラムを参照する方法を教えてください

Back to archive index

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/




groonga-dev メーリングリストの案内
Back to archive index