前回は、2003年の9月半ばにコンパクトな検索エンジンの体裁が整った所までをご紹介しました。今回はどのようにして現在の検索エンジンに至ったかについてのお話です。
開発方向の模索
2003年の7月時点のFINDSPOTのバージョンは0.1でしたが、小規模な機能追加や改良ごとに0.1づつバージョンをアップさせ、2003年の9月半ば時点では0.8.2というバージョン番号になっていました。ここまでが前回のお話です。このときは、最低限実現したいと考えていた機能は実装できたけれども、世に出すにはもうひとつ何かが足りない、そんな印象を抱いていました。バージョン番号が0.8なのだから、漠然とあと20%位の機能を実装すれば良いのだろうと考えていましたが、後々それがとんでもなく大きな誤算であることがわかります。第1回目に紹介したような当初見えていたはずの課題が、早くもぼやけ始めていたのです。
開発プロジェクトを始める前に課題やその優先順位が客観的にはっきりと認識できていても、作業にかかるとぼやけてしまうことがあります。筆者の場合、プログラミングにとりかかると、目の前の課題に集中せざると得ないので、どうしても近視眼的になってしまいます。そんなときには、なるべく目の前の課題から離れて全体を見るように努力しているのですが、なかなか難しいものです。
当時手がけていた、数年間に渡るアクセシビリティ関連のプロジェクトが忙しくなった関係で、その後FINDSPOTの開発にはほとんど時間を割けない状態が1年近く続きます。この間、FINDSPOTをオープンソースにして公開する方法も検討しましたが、FINDSPOTの開発時間も割けないような状態では、最低限の電子メールなどでのサポートも難しいだろうとの判断で取りやめました。ブランクの間は、今後の開発の方向性が定まらなかったこともあり、検索の最適化の実験を行った以外に大きな成果はありませんでした。この間「FINDSPOTの開発の方向性がぶれない、電車でいえばレールのようなものが必要だけれども、いったい何をレールにしたらよいのだろうか」との自問自答を繰り返していました。
見えてきた方向性
そんな折、全文検索機能を備えたシステム開発案件で筆者の会社から、検索エンジンを提供してほしいという依頼が舞い込みます。ちょうどこのころ、FINDSPOTに欠けている部分は、自分の判断よりも実際の開発案件に照らせば自ずと明らかになるはずだから、開発案件を見つけてFINDSPOTを実用的なエンジンにしようとの結論を下していました。つまり、課題がぼやけないように開発案件の要件を開発目標とすることで、開発の方向性にぶれが生じないようにしようとの工夫です。渡りに舟とばかりにこちらの開発に乗り出すことにしました。今後開発を進める機能については独断ではなく、実際の開発案件で本当に必要とされる機能に絞るというポリシーに、大きく舵を切ることにしたのです。
実案件化への道のり
要件を分析すると、新たに次のような機能が必要であることがわかりました。
- インデックスに新規文書をリアルタイムで追加するために、検索機能を動作させながら同時にインデックスの追加や削除が可能なこと
- 全文検索と文書のプロパティ情報(作成日付、分類、作成者など)と組み合わせたAND, OR, NOT検索が可能なこと
- 文書のプロパティ情報の型、名称については自由にカスタマイズが可能なこと
- 本文、タイトル以外にユーザ定義のプロパティが全文検索対象として利用できること
- 特定のプロパティのみに限定した全文検索が可能なこと
- 100万件の文書数が検索可能なこと
- 複数インデックスの横断検索
- 検索クライアント用のクラスライブラリ
- Windows版での検索エンジンのサービス化
- 複数サービスの同時稼働
- ライセンスフリーな書誌データベース対応(PostgreSQL, SQLite対応)
- インデックス作成時間と検索時間の高速化
- 特定の文字列の近傍に別の文字列が存在するという条件のADJ、NEAR検索機能
- 「ヴァイオリン」の検索で「バイオリン」を含む文書をヒットする等の曖昧検索機能
- PHPによるクライアントCGIのサンプルコード
- Windows版のインストーラの作成
- 特定の検索結果数以上は検索結果をソートしない上限設定機能
これらの機能を実装するには、検索エンジンの全文検索のロジック以外は軒並み書き直しに近い作業が必要になりました。全文検索のインデックス定義をXMLで記述したスキーマの設定ファイルで指定できるようにしたり、検索式のパーサを複雑な構文を解析できるようにLemonというコンパイラコンパイラで本格的に実装したり、複数インデックスを扱えるようにしたり、書誌情報のデータベースとしてPostgreSQLを再度利用できるようにしたり、SQLiteにも対応したりと、FINDSPOTの開発初期の数倍の作業量が必要でした。
最初の開発案件の納品を機に、FINDSPOTのバージョンは1.0となりました。FINDSPOTの専用コードのステップ数はVersion 0.8.2の8,700行から40,000行ほどに大きくなりました。
(FINDSPOTのビルドにはこの他に12万行ほどの筆者の作成したC++のクラスライブラリが必要です)
その後のいくつかの開発案件で必要になった主立った機能は次の通りです。
- 構文エラーやエンコーディングの自動判定に強いHTML, XHTML用の専用フィルタ
- IFilterを用いたMicrosoft Office、PDF等からのテキスト情報抽出用フィルタ(Windows版のみ)
- 検索エンジンとクライアントの接続時の認証機能強化
- 64bitの整数型の文書プロパティのサポート
- 複数のプロパティ情報による検索結果のソート
- 複数のプロパティ検索時に検索式をシンプルにし検索速度を上げる最適化
- 大量の文書を一度にインデックスするバルクインデックス作成機能
- 別マシンでインデックスを作成し、検索エンジンにインデックスをインポートするポータブルインデックス作成機能
- ○付き数字と通常の数字を区別しない等の設定を可能にする等価文字の指定機能
現在のFINDSPOTの最新版は1.3.6というバージョンです。コードのサイズは45,300行ほどになります。先に述べたような、バージョン0.8から比べてあと20%くらいの機能が実現できればバージョン1.0と漠然と思っていたのは、とんでもない誤りであったことになります。このような筆者の見通しの悪さを正せたのが実際の開発案件であり、またFINDSPOTを使っていただいた開発会社の方々の力です。実際の開発案件や、開発会社の方々からの貴重なフィードバックがなければ今日のFINDSPOTは存在しません。この場を借りて関係者の方々にお礼を申し上げたいと思います。