隔週連載groonga

第4回 rroongaを使ったソースコード検索エンジンMilkode

この記事を読むのに必要な時間:およそ 4 分

はじめまして,おんがえしと申します。

今回は私が作っているソースコード検索エンジンのMilkodeにて,rroonga(とその内部で動くgroonga)がどのように使われているのかを紹介します。

Milkodeの検索画面

Milkodeの検索画面

ソースコードを検索するということ

プログラマの仕事はプログラムを書くことですが,同じくらい「検索する」ことは多いのではないでしょうか。

  • ある関数の名前を変えたいので使っている箇所をすべて見つけたい
  • ライブラリの仕様が変わった。使っているコードはどこだったか?
  • コードリーディング中。今読んでいる関数の実体はどこにあるのか?

ベーマガを買ってゲームのプログラムを写経していた頃から時代は進み,WebにアクセスすればゲームやOS,Webアプリなどのソースコードを無料※1で手に入れることができるようになりました。必要なものをソースコードから検索し,知識として取り込んでいく技術は今後ますます重要になってくるはずです。

※1
ライセンスの制約はありますが,それでも10年前を考えるとGitHubで何でも読めるのはとても幸せなことです。

既存の検索ツールの問題点

私もソースコードを検索するためのツールとして色々なものを使ってきました。その内に「こうなったらいいのにな」とか「こういう機能がほしい」といった要求が自然と湧いてくるようになりました。

Wikipediaの「全文検索」の項から言葉を借りて,順番にファイルの中身を調べて検索するタイプをgrep型あらかじめ索引(インデックス)を作っておき索引データを元に検索するものをインデックス型と呼ぶことにします。

それぞれのタイプの不満を挙げてみます。

grep型の不満
  • ファイル数が増えると遅い
  • 検索のたびに*.rbなどと対象のファイルを指定するのが面倒。基本はプロジェクト単位で検索したい
  • .git.svn*~などは自動で検索対象から外してほしい※2
  • .gitignoreの除外対象に含まれているものも検索対象から外してほしい※2
  • ブラウザからも検索したい
インデックス型の不満
  • 複数のキーワードにマッチするを見つけることができない
    • ファイル単位で見つけるものが多い
  • 非公開のコードも検索対象に含めたい
    • Webアプリのみ提供しているタイプのものはオープンソースしか検索対象にできない
  • grep型と同じくらい,簡単にインストールできるようにしてほしい

これらの問題を上手く解決することができればそれなりに需要があるのではないかと考え,Milkodeの開発が始まりました。前身となるgrenを作り始めたのが2010年の7月なのでもう2年以上携わっていることになります※3)。

※2
この辺りの問題を解決しようとしているgrep型のツールもあります。agが有名です。
※3
幸か不幸かまだまだやりたいことが尽きません。もうちょっとで1.0を出せそうな気がしています。

さてどうやって作ろう?

ソースコード検索エンジンを作ろうと思い立ったものの,grep型はともかく,インデックス型のものを作るにはいったい何をどうすればいいのかまったく分かりませんでした。どうも全文検索エンジンと呼ばれる類いのソフトウェアを使えばよいことが分かってきたため,次の要素を条件に全文検索エンジンの選定(Googleでキーワードを変えながらカチカチすすること)を始めることにしました。

  • 主要なOSで使える
  • (比較的)簡単にインストールできる
  • 日本語の情報が豊富

groongaとの出会い

いくつかの検索エンジンを調べていくなかで,カラムストア機能付き全文検索エンジンのgroongaに辿り着きました。

他にも候補はあったのですが,次の理由でgroongaに惹かれたような気がします。

  • Sennaという有名な検索エンジンの後継(らしい)
  • 他の検索エンジンと比べると後発のため,老舗のものにありがちな問題が解消されていそう
  • 日本人の開発者を中心に作られているので日本語の情報が豊富
  • MLのログを読むと質問やバグ報告に対するレスポンスも速い
  • 若いプロジェクトなのでパッチも積極的に受け入れてくれそう

正直検索エンジンに対する知識が皆無だったため,最後はMLのログやサイトの雰囲気から感じられるフィーリングで決めたと思います。

その後,須藤さんや森さんをはじめとするgroonga開発者の皆さんとお会いする機会があったり,須藤さんとTwitterでソフトウェア開発したり,rroongaにWindows関連のパッチを取り込んでもらえたりしたので,最初の直感は間違いではなかったのかなと思います。

もう少し真剣にリファレンスマニュアルなどを読み始め,最終的に「groongaを使おう!」となった決定打は次の3点だったと記憶しています。

  1. 単体で全文検索+ストレージとして動作する
  2. Rubyだけで書ける
  3. ライブラリとして動作する

順に説明していきます。

1. 単体で全文検索+ストレージとして動作する

groongaの場合は,次の両方をgroongaだけで行うことができます。

  1. ファイルの内容をデータベースに格納
  2. 格納されたデータを全文検索

別途MySQLなどのストレージエンジンのインストールを要求するタイプもあったのですが,Milkodeのようなデスクトップアプリとしても動作するものは必要なソフトウェアの数は極力少ない方がよい※4のでとても助かりました。

※4
デスクトップアプリケーションは必要なソフトが増えるたびにインストールしてもらえる確率がどんどん下がります…。

2. Rubyだけで書ける

groonga本体はC言語で書かれていますが,ラングバプロジェクトのライブラリを使えば基本的な操作はすべてRubyだけで書くことができます。次はrroongaで作るブックマークアプリケーションの例です。

require 'rubygems'
require 'groonga'

# データベースの作成
Groonga::Context.default_options = {:encoding => :utf8}
Groonga::Database.create(:path => "bookmark.db")

# テーブルの定義
Groonga::Schema.define do |schema|
  Groonga::Schema.create_table("Items", :type => :hash) do |table|
    table.text("title")
  end

  Groonga::Schema.create_table("Terms",
                               :type => :patricia_trie,
                               :key_normalize => true,
                               :default_tokenizer => "TokenBigram") do |table|
    table.index("Items.title")
  end
end

# レコードの追加
items = Groonga["Items"]
items.add("http://gihyo.jp"                  , title:"技術評論社")
items.add("http://ja.wikipedia.org/wiki/Ruby", title:"Ruby")
items.add("http://www.ruby-lang.org/ja"      , title:"オブジェクトスクリプト言語Ruby")

# 全文検索
result = items.select {|record| record.title =~ "Ruby"}

# 結果を集計
p result.map{|record| record.title} #=> ["Ruby", "オブジェクトスクリプト言語Ruby"]

Milkodeではrroongaを使っており,データベースの作成,テーブルやレコードの管理,全文検索まですべての処理をRubyだけで記述しています。

3. ライブラリとして動作する

rroongaはRubyGemsライブラリとして提供されているため,インストールはgemコマンド一発です。

$ gem install rroonga

bundlerであればGemfileに次の記述を一行追加するだけです。とっても簡単ですね!

gem 'rroonga'

すべての機能はRubyのクラスやメソッドとして提供されているため,外部プログラムを呼び出す必要もありません。外部プログラムが絡むとOSによって挙動が変わってしまうことがあるため,この辺もありがたかったです。

これらのメリットと,軽くテストした感じの使い勝手も良さそうだったため,rroongaを使って開発することに決めました。

著者プロフィール

おんがえし(ongaeshi)

プログラマ。職業プログラマの傍らでオープンソースのソフトウェアを作る。最近作ったのはMilkodeFireLinkauto-shell-command.elなど。こつこつと何かを作りながら生きていければよいと思っている。

Twitte:@ongaeshi
ホームページhttp://ongaeshi.me

コメント

コメントの記入