社内文書の検索システム
思い立って仕事の合間にブラウザから閲覧する社内文書の全文検索システムを作っている。
【ざっとした要件】
■PDF、Word、Excel、PowerPointのファイルに対応
■検索エンジンはSennaを利用
Hyper EstraierとNamazuが候補だった。
前者は付属のCGIが便利だけど改造するのが面倒で、後者は珍しさと真新しさに欠けるので。
技術的な優位性とかは考慮せず。
ludiaが使えるので。
■ファイルをアップロードするとその場でインデックスを更新
PDFはludiaのマニュアル通りに、他はテキストに変換してINSERT。
■アップロード処理中はプログレスバーを出す
カッチョイイ!
■検索クエリはGETで渡す
外部サービスと結合しやすいし。
■追加されたファイルの情報を表示
トップページに更新情報として最近追加されたファイルを表示してあげる。
非同期通信で定期更新。
■検索結果にスニペットを表示
ludiaの関数が使える。
誤検出があってもファイルを開く前にユーザが見て判断できる。
■SennaのバインディングはPostgreSQL
MySQLだと本体にパッチを当てないといけないのでPostgreSQLに。
【いろいろ環境設定】
ExcelファイルをHTMLに変換するツールはxlhtml。Mac OS X 10.4.9でxlhtml-0.5をビルドしたら「cole/Makefile.am: required file `./depcomp’ not found」というエラーが出て失敗した。下のようにやってみた。
$ aclocal $ autoconf $ automake --add-missing $ make $ sudo make install
これで通った。
wv2がfinkに入っていたのでインストールしてみたが、wvWareの使い方の方がウェブでたくさん見つかるのにwv2だといろんなコマンド群が入らないのでwv1系をインストール。途中でlibgsfのバージョンが低いと怒られたが、finkだとlibgsfじゃなくてlibgsf1.114という名前になっていたので、いったんlibgsfを外して入れ替える。このパッケージ構成はよくわからない。
コピー禁止のPDFファイルをインデックス化するために、こちらを参考にxpdfをちょっと変更。まあ、自分だけで使うツールだし、いいよね。ね?ね?
SennaとludiaのインストールはThinkITの記事やマニュアルを参考に。今回はMecabを使うことにした。
DBはPostgreSQL。createdbの際、エンコーディングはUTF-8を指定した。
テーブルとファンクション、インデックスの作成はこんな感じ。ウェブからアップロードされたファイルは新しくユニークなファイル名を付与されて適当なパス上に保存される。元の名前はDBに格納されて、検索結果ページでクリックされるとattachmentとして元のファイル名でインライン表示されるようにした。ええ、SQLもDBもあんまり得意じゃありません。
CREATE OR REPLACE FUNCTION pgs2pdftotext1(TEXT) RETURNS TEXT AS '$libdir/pgsenna2', 'pgs2pdftotext1' LANGUAGE 'C' STRICT IMMUTABLE; CREATE TABLE search ( search_id serial PRIMARY KEY, filename text NOT NULL DEFAULT '', --元のファイル名 filepath text NOT NULL DEFAULT '', --新たに付与したファイル名 regist_date timestamp without time zone NOT NULL DEFAULT '2007-01-01 00:00:00' ); CREATE INDEX idx_search_filepath ON search USING fulltextb(pgs2pdftotext1(filepath));
PDFファイルのデータをINSERTする場合、こんなSQLでインデックスが作成される。
INSERT INTO search ( filename, filepath, filetext, regist_date ) VALUES ( '元のファイル名', '新しいファイルへのパス', pgs2pdftotext1('新しいファイルへのパス'), now() );
PowerPointやExcel、Wordのファイルもそれぞれ => テキスト => PDFと変換してINSERTは常に同じコマンドを使うようにしてもいいんだけれど、それも不健康な感じなのでテキストとして普通に処理することにした。now関数を使うけど、別にDBのレプリケーションはしないからいいや。
【実装しないもの】
今回の作業で実装しない機能は:
- クローラ(Window環境用も作りたくなるから)
- ファイル形式の自動判定(無理!拡張子で判定)
- 検索結果にタグ付けして次に簡単に呼び出せるようにする(時間が…)
クローラはないけど、特定のディレクトリ内のファイルを一気に処理するバッチファイルは作っておいた。最初のデータ入力が面倒だし。
もしかしたら実装しちゃうかも:
- 検索語のサジェスチョン(インクリメンタルサーチで今までに入力されたデータから引っ張ってくる)
こんなもんかな。さて、作業開始。
コメントを残す