株式会社クリアコード > ククログ

ククログ


るりまサーチ: Rubyでgroonga使ってリファレンスマニュアルを全文検索

先日、るりまの成果物であるRubyのリファレンスマニュアルを検索するWebアプリケーションるりまサーチを公開しました。

るりまサーチ

OpenSearchにも対応しているため、Firefoxの右上の検索窓から検索することもできます。

これまでも、るりまの成果物はBitClustを使ってWebブラウザから見ることができました*1。しかし、BitClustのWebインターフェイスは検索機能が弱く、目的の情報にたどり着くのが難しいと感じたことがあったのではないでしょうか。例えば、全文検索ができなかったり、そもそも検索がとても遅かったりしました。

るりまサーチでは全文検索エンジンとしてgroongaを利用することにより、高速な全文検索機能と使いやすい絞り込み機能を実現しています。それでは、るりまサーチの機能とその実装について簡単に紹介します。

機能

るりまサーチは多くの情報を絞り込んでいきながら目的の情報に到達することを意識したインターフェイスになっています。そのため、できるだけ簡単に絞り込んでいけるような機能を組み込んであります。

ここでは、絞り込みに関する機能を2点だけ紹介します。

ドリルダウン

groongaの得意な機能の1つはドリルダウンと呼ばれる、検索結果の中から特定の値をグループ化し、それぞれのグループのレコード処理を数える処理です。るりまサーチでもこの機能を利用して絞り込みやすいインターフェイスを提供しています。

ドリルダウン

るりまサーチではページ上部にそのときに絞り込める条件を表示します。例えば、トップページではマニュアルの種類によって絞り込めるリンクを表示しています。

このとき、事前に絞り込んだ後のレコード数も表示しています。この時点で絞り込み後のレコード数を数えているので、絞り込んだ後にレコード数がないリンクを表示しないことができます。つまり、「リンクを辿ったけど絞り込んだらマッチするレコードがない!」という状況を防ぐことができます。

便利に絞り込めるリンクを提供し、その一方で、無駄な絞り込みを行わずに済むようになっています。

条件解除

簡単に条件を絞り込めるようにするだけではなく、簡単に条件を解除することもできます。これは様々な絞り込みを行いながら目的の情報に辿りつけるようにするためです。

条件解除

ページ上部にはどのような条件で絞り込んでいったかが表示されるようになっています。それぞれの絞り込み条件は条件の横にあるリンク*2を辿るだけで簡単に解除することができます。

絞り込みすぎてしまったときは、これで条件を解除して違う条件で絞り込んでいくことができます。

実装

るりまサーチはRuby 1.9.1とRackとrroongaを用いて実装されています。rroongaはgroongaをRubyから利用するためのRubyバインディングです。るりまサーチではgroongaをサーバとしてではなく、ライブラリとして利用しています。

rroongaはgroongaの高速な機能を活かしたまま、より使いやすいRubyらしいAPIを提供しています。るりまサーチはそんなrroongaを使って、すっきりとした記述で実現されています。ここでは、rroongaを使ったコードを2つ紹介します。

スキーマ定義

groongaはRDBと同じようにデータの格納場所毎に型を持っています。groongaにデータを格納する前に格納場所を用意する必要があります。

rroongaでは格納場所の定義(スキーマ)をより宣言的に記述するためのAPIを用意しています。以下は検索対象の情報を保存する「Entries」テーブルの定義です。RDBなどのスキーマを見たことがあるなら、この定義からgroongaがどのようなデータを格納できるようになるかを想像できるのではないでしょうか。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Groonga::Schema.define do |schema|
  schema.create_table("Entries",
                      :type => :hash,
                      :key_type => "ShortText") do |table|
    table.short_text("name")
    table.short_text("local_name")
    table.short_text("label")
    table.text("document")
    table.text("signature")
    table.text("description")
    table.reference("type", "Types")
    table.reference("class", "Classes")
    table.reference("module", "Modules")
    table.reference("object", "Objects")
    table.reference("version", "Versions")
    table.reference("visibility", "Visibilities")
  end
end

このように、Rubyでは宣言的に処理を記述することがわりとよく行われます。これは、内部DSLとも呼ばれ、やりすぎる人も出るほどです。例えば、上記のような記述を以下のようにすることもできますが、これは少しやりすぎではないかと感じます。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
Groonga::Schema.define do
  create_table("Entries",
               :type => :hash,
               :key_type => "ShortText") do
    short_text :name
    short_text :local_name
    short_text :label
    text       :document
    text       :signature
    text       :description
    reference  :type, :Types
    reference  :class, :Classes
    reference  :module, :Modules
    reference  :object, :Objects
    reference  :version, :Versions
    reference  :visibility, :Visibilities
  end
end
検索条件

rroongaでは検索条件をクエリ文字列ではなく、Rubyの式として記述することができます。

例えば、「name」カラムの値が「Regexp」であるレコードを検索するときは以下のようになります。

1
2
3
entries.select do |record|
  record.name == "Regexp"
end

「name」カラムの値が「Regexp」あるいは「description」カラムに「正規表現」が含まれているレコードを検索するときは以下のようになります。

1
2
3
entries.select do |record|
  (record.name == "Regexp") | (record.description =~ "正規表現")
end

「name」カラムか「description」カラムに「encoding」を含むレコードを検索するときは以下のようになります。ただし、「name」カラムにマッチした場合はスコアをあげて、より上位に表示するようにします。

1
2
3
4
5
6
7
entries.select do |record|
  target = record.match_target do |match_record|
    (match_record.name * 100) |
    (match_record.description)
  end
  target =~ "encoding"
end

DataMapperSequelなど文字列ではなくRubyの式で条件を指定できるようにするORマッパーはいくつかありますが、最終的にそれらはSQLになります。しかし、rroongaの場合はRubyで書いた式がそのままgroongaのネイティブな条件式になります。カッコいいですね。

また、ORマッパーも少しやりすぎてしまう傾向がある分野ですが、rroongaはやりすぎることなく、Rubyらしさを保ったまま条件式を指定できているのではないでしょうか。少しやりすぎてしまうと、Symbolにメソッドを追加してしまったりします。

まとめ

Rubyのリファレンスマニュアルを検索するWebアプリケーション「るりまサーチ」の機能と実装を簡単に紹介しました。

るりまサーチを使うことでるりまプロジェクトの成果物であるRubyのリファレンスマニュアルをより便利に活用することができます。

また、るりまサーチの実装はgroongaのRubyバインディングであるrroongaのよいサンプルでもあります。groongaをRubyから利用しようと考えていた方はGitHub上にある、るりまサーチのソースコードを読んでみるとよいでしょう。ライセンスはLGPLv3+です。

るりまサーチはSinatraなどのフレームワークを使わずに、直接Rackを使っています。そのような場合にどのようにテスト環境を構築するか、というのもいつか紹介できるとよいですね。今、興味のある人はソースコードを見てください。

このように、るりまサーチにはまだおもしろいところが色々あるのですが、今回はこのへんにしておきます。

*1 自分で設定するのが面倒な場合はokkezさんが公開しているBitClustを利用することもできます。

*2 画像にしたいですね。

タグ: Ruby

この記事の続き

2010-04-27

«前の記事: Ruby 1.8.7/1.9.1どちらでも使えるWindows用バイナリ入りgemをDebian GNU/Linux上で作る方法 最新記事 次の記事: groonga用Muninプラグイン»
タグ:
年・日ごとに見る
2008|05|06|07|08|09|10|11|12|
2009|01|02|03|04|05|06|07|08|09|10|11|12|
2010|01|02|03|04|05|06|07|08|09|10|11|12|
2011|01|02|03|04|05|06|07|08|09|10|11|12|
2012|01|02|03|04|05|06|07|08|09|10|11|12|
2013|01|02|03|04|05|06|07|08|09|10|11|12|
2014|01|02|03|04|05|06|07|08|09|10|11|12|
2015|01|02|03|04|05|06|07|08|09|10|11|12|
2016|01|02|03|04|05|06|07|08|09|10|11|12|
2017|01|02|03|04|05|06|07|08|09|10|11|12|
2018|01|02|03|04|05|06|07|08|09|10|11|12|
2019|01|02|03|04|