ナレッジマネジメントはじめの一歩

Namazuによる全文検索システムの導入

社内向けイントラネット、あるいは外部向けの情報公開用Webサーバを無事構築して、しばらくすると直面する事実があります。どこに必要な情報があるのか、探し出すのが大変なのです。せっかくコンピュータを使っているのですから、コンピュータ自身に探してもらいましょう。

主な内容
全文検索システムとは
Namazuの入手とインストール
インデックスの作成 基本編
検索の基本
インデックスの作成 応用編
Webインターフェイスを作る
インデックスの自動更新

関野史朗
2000/12/23

全文検索システムとは

 全文検索システムは、データベースの一種です。ただ、一般的なデータベースはあらかじめ検索用の項目を作成しておきますが、全文検索システムではすべてのデータが検索の対象となります。ここが「全文」といわれるゆえんです。

 もっとも、一般的なデータベースでも全文検索は可能です。ただ主たる目的ではないためにインデックスが作成されておらず、大変時間がかかってしまうのです。逆に全文検索システムでは検索対象を文法的に解析して単語に分割し、自動的にインデックスを作成します。このためインデックス作成には時間がかかりますが、検索自体は高速です。

 最も知られた全文検索システムは、いわゆるWeb検索エンジンです。あれほど扱う情報が多くなると大規模なシステムが必要ですが、自社のサーバだけならフリーのシステムでも十分対応できます。それが今回紹介するNamazuです。

Namazuの入手とインストール

 Namazuの1次情報源はhttp://www.namazu.org/です。ここからソースコードを入手できますし、チュートリアルやマニュアルもあります。もちろんRPMやdebといったバイナリパッケージも用意されているので、それを使えば簡単にインストールできます。

 ソースコードからコンパイルしてインストールする場合、Namazu以外に必要なプログラムが意外にあります。http://www.namazu.org/doc/tutorial.html#prep-makeに記述がありますが、

  • Perl
  • nkf
  • KAKASIまたはChasen
  • MMagic

です。さすがにPerlはどんなディストリビューションでも標準でインストールされているでしょう。しかしそれ以外は、意識してインストールしないと入っていないと思います。でもこれらのインストールまで解説すると大変なので、パッケージなどを使ってすでにインストール済み、という前提で話を進めます。

 入手したソースコードはたいていgzipで圧縮されたtarファイルなので、

$ tar zxvf zxvf namazu-2.0.4.tar.gz

で展開する必要があります。この場合はnamazu-2.0.4というサブディレクトリに展開されます。無事展開が終わったら、そのサブディレクトリに移動して、

$ ./configure

を実行します。ログインシェルとしてcshやtcshを使っている場合は、

% sh configure

とした方が確実です。この実行にはちょっとした時間がかかります。

 無事実行が終了したら、今度はmakeです。単純に、

$ make

としてください。最近のLinuxディストリビューションなら、まずエラーは起きずにコンパイルが終了するはずです。うまくコンパイルできたら、スーパーユーザーになってから

# make install

を実行してインストールします。

 なお、デフォルトでは/usr/local以下にインストールされますが、configureの引数として--prefixを使うと任意の場所に変更できます。例えば

$ ./configure --prefix=/usr/share

などですが、混乱を避けるためにデフォルトの/usr/localにインストールすることをお勧めします。

インデックスの作成 基本編

 無事Namazuがインストールできたら、次に行うのがインデックスの作成です。このときに使うのはmknmzコマンドで、

$ mknmz ~/public_html

とすると~/public_html以下にあるファイルに対するインデックスをカレントディレクトリに作成します。基本はこれだけです。

 もっとも、mknmzにはさまざまなオプションがあります。詳しくはマニュアルを見てもらうとして、よく使うものをいくつか紹介してみましょう。

-O
     
インデックスの出力先を指定します
-s
     
チェックポイント機構を有効にします。これはある程度のデータを処理した時点でデータを書き出し、処理プロセスを再起動します。これによって、大規模なデータを処理したときでもプロセスが膨れ上がることがなくなります
-c
     
単語に分解するプログラムとしてChaSenを使います
-k
     
単語に分解するプログラムとしてKAKASIを使います

 ここで、KAKASIとChaSenがどう違うのかに触れます。

 もともとKAKASIは漢字仮名交じり文を仮名だけ、あるいはローマ字表記に変換するために作られました。そこに分かち書き機能が追加されたため、比較的シンプルなルールで高速に動作します。

 一方ChaSenは最初から日本語を構成する単語を分析する形態素解析プログラムとして開発されています。そのためやや動作が遅く使い方が難しいものの、より正確な解析が可能になります。

 実際に利用した感じでは、KAKASIで十分実用になります。

検索の基本

 さて、インデックスを作ったら、早速使ってみましょう。一番基本となるのは、コマンドラインで実行するnamazuコマンドです。ソースコードからコンパイルしてインストールすると、標準では/usr/local/bin/namazuになります。

 しかし、個々のディストリビューション用に作られたパッケージだと、それぞれ違った場所にインストールされます。いずれにしても、普通はコマンドサーチパスに設定された場所にインストールされるはずなので、コマンドラインからいきなり実行できるはずです。

 書式としてはnamazuコマンドに続けて、検索したい文字列、インデックスを作っておいたディレクトリの順で指定します。インデックスは複数指定できますが、省略したときにどこを探すかはパッケージによって違います。ソースコードからのインストールだと、普通は/usr/local/var/namazu/indexになります。明示的に指定した方が、間違いが少なくなって使いやすいです。

 複数の単語で検索したいときは、ダブルクオーテーションでくくって単語を並べます。このとき、単純に空白で区切って単語を並べると、すべての単語を含んだファイルが検索結果として表示されます。例えば

"Linux Namazu"

とすると、「Linux」と「Namazu」の両方を含んだファイルが結果として表示されます。

 いずれかの単語を含むファイルを検索したいときには、単語と単語を「or」で結んで並べます。同じように例を挙げると、

"Linux or Namazu"

という指定は「Linux」か「Namazu」のどちらかを含む、という意味になります。

 また、指定した単語を含まないという指定は「not」を付けて表現します。

"Linux not Namazu"

とすると、「Linux」は含むが「Namazu」は含まない、ということになります。

 もう少し高度な指定方法として、カッコでくくってグループ化できます。

" ( turbo or redhat ) and namazu"

とすれば、「turbo」か「redhat」を含み、なおかつ「namazu」を含む、ということです。このとき、カッコの両側には空白が必要です。

 フレイズ検索という機能もあります。ダブルクオーテーションか中カッコでくくって単語を並べると、その順番に単語が出てきたときに一致したことになります。

"{ readhat linux }"

とすると、「redhat」と「linux」の両方があるだけでなく、この2つがこの順番で出てきたときだけに一致します。ただ、namazuのフレイズ検索はときどき間違えるそうなので、気を付けて使った方がいいでしょう。

 もう1つ、部分一致検索機能にも気を付けた方がよいでしょう。これには前方一致、中間一致、後方一致の3種類があり、それぞれ

  linux* linuxで始まる
  *linux* linuxを含む
  *linux linuxで終わる

となっています。で、どこに気を付けるかなのですが、漢字で構成される単語を検索すると、時として思ったように一致しないのです。例えば「思考」で検索すると「思考機械」に一致しないといったことが起こります(これは例なので、必ずしもこの通りとは限りませんが)。思ったようにヒットしないときは、"思考*"とか"*思考"、"*思考*"などとして検索してみてください。

 これをもっと汎用的にしたのが、正規表現検索です。正規表現は/で囲って表します。例えば

"/インターフェ[ーイ]ス/"

とすると、「インターフェース」か「インターフェイス」のいずれかに一致します。正規表現はとても奥が深いので、ここでは機能があるという紹介にとどめます。コードとしてはRuby(http://www.ruby-lang.org/)というオブジェクト指向スクリプト言語のものを利用しているそうで、書式はPerlに近いとドキュメントにありました。

 最後に、フィールドを指定して検索する方法もあります。Subject:、From:といったフィールドに含まれる文字を検索するので、メールやニュースのデータを検索するのに便利です。このときは、+で始めます。例えば

"+subject:linux"

とすると、「Subject:にlinuxが含まれる」という意味になります。

 さてこうして検索すると、結果としては最も重要と思われる20件だけが表示されます。これは見出しなどに使われているといった点を考慮してスコアをつけ、その点数が多い順となっています。表示する件数をもっと増やしたいのなら、-nオプションで指定できます。また、すべてを表示したいなら、-aオプションが使えます。この場合はパイプを使ってlessなどに結果を渡さないと、あっという間に画面からスクロールアウトしてしまうので気を付けてください。

 標準では、結果として表示されるのは単純なテキストファイルです。-hオプションを使うとHTMLで出力できますが、これを使うのであればWebインターフェイスを作った方が便利でしょう。ほかにもオプションはありますが、詳しくはマニュアルを見てください。

インデックスの作成 応用編

 さて、インデックスの作成と検索の基本が分かったところで、ちょっとした応用編です。

 まず、mknmzコマンドのオプションから。詳しくはマニュアルを読んでいただくとして、使うと便利なオプションを紹介します。

 最初に、インデックスを作成する対象を限定するためのオプションとして、--target-list=FILE--allow=PATTERN--deny=PATTERN--exclude=PATTERNがあります。

 前の2つは、対象となるファイルを明示的に指定する方法です。--target-listでは、FILEで指定したファイルの中に書いてあるファイルをインデックス作成の対象とします。--allowは、正規表現を使って対象となるファイルを指定します。HTMLファイルだけ、とかテキストファイルだけ、といった指定ができるわけです。ただ、この方法では日々増えていくデータに対処するのはなかなか大変です。増えたファイルをいちいち指定しなければならないからです。

 対して--denyと--excludeは、インデックスの対象としないファイルを指定します。--denyは正規表現でファイル名を、--excludeは正規表現でパス名を指定します。イントラネットやインターネットで情報を公開する場合、検索されては困る情報の方が少ないはずです。この2つのコマンドを使って、公開できない部分を指定する方が労力は少なくて済むでしょう。

 今度は、対象となるファイルの種類についてです。mknkzコマンドは、対象となるファイルを分析して適切なフィルタ処理を行っています。このとき使われるフィルタは、/usr/local/share/namazu/filter(ソースコードからインストールした場合の標準的な場所)にあります。普通のオフィスでしたら、MS-WordやExcelで作ったデータがあることでしょう。一太郎やPowerPointなどもあるかもしれません。こうしたデータを扱うには、専用のフィルタを前述の場所に用意しておけばいいのです。何を用意すればいいのかは、マニュアルに記述してあります。一例を挙げると、

  Word wvWare
  Excel xlHtml
  PowerPoint doccat
  一太郎 doccat

となります。

Webインターフェイスを作る

 さて、これでかなり自由にインデックス作成と検索を行えるようになったと思います。しかし、このままではLinuxにログインしてコマンドをタイプできる人でないと使えません。Webベースのインターフェイスを作れば、だれでも検索できます。これを実現するのは比較的簡単で、標準で用意されているnamazu.cgiを使えばよいのです。

 これもパッケージによってどこにインストールされるのかは違ってきます。ソースコードから標準的にインストールしたときは、/usr/local/libexec/namazu.cgiになるので、WebサーバのCGIディレクトリにコピーします。念のため、パーミッションのチェックもしておきましょう。だれでも実行できて読み出せるようにしておくのが一番簡単な設定です。セキュリティのことを考えると、読み出しと実行ともにWebサーバか、Webサーバが属するグループだけに許可しておくのが安全でしょう。

 namazu.cgiの動作を決定するのは、同じディレクトリにある.namazurcです。いろいろな設定が可能ですが、最低限LANGをjaにして日本語での表示を可能にしておきましょう。また、Webで公開するのなら検索結果へのリンクはURLで表示したいもの。しかしnamazuの検索結果は、デフォルトではパス名です。これを置き換えるのが、Replaceです。Replaceに続けて置き換えたいパス名、置き換えるべき文字列を設定します。例えば、

Replace /usr/share/public/www/ http://www.atmarkit.co.jp/

とするわけです。この場合は、/usr/share/public/wwwがWebサーバのドキュメントルートディレクトリに相当します。

(注)
パス名(例の場合は/usr/share/public/www/)と文字列(同http://www.atmarkit.co.jp/)は続けて1行で記述します。

 検索するためのWebページでは、FORMエレメントを使います。実際にはNMZ.headとNMZ.head.jpが参照されるので、必要に応じてこの2つのファイルを作り出すテンプレートを加工します。例によって標準では/usr/local/share/namazu/template以下にありますが、ディストリビューションやパッケージによって違うはずなので、locateコマンドなどを使って探してください。

 具体的なコーディングをマニュアルから抜粋すると、複数のインデックスからいずれかを選択して検索する場合は、

<strong>検索対象:</strong>
<select name="idxname">
<option selected value="foo">foo
<option value="bar">bar
<option value="baz">baz
</select>

と記述します。ここでfooを選択すると、デフォルトのインデックスディレクトリ下にあるfooサブディレクトリ内のインデックスを使います。

 複数のインデックスを選択して使うなら、こんなコードになります。

<strong>対象インデックス</strong>
<ul>
 <li><input type="checkbox" name="idxname" value="foo">foo
 <li><input type="checkbox" name="idxname" value="bar">bar
 <li><input type="checkbox" name="idxname" value="baz">baz
</ul>

 この場合も、選択した項目はデフォルトインデックスディレクトリ下のサブディレクトリにインデックスがあるものとして処理されます。

インデックスの自動更新

 ここまでくると、Webサーバ上に公開したドキュメントをだれでも簡単に検索できるようになります。しかし、新陳代謝の活発なサーバだと、すぐにインデックス情報が古くなってしまいます。新しいドキュメントを追加するたびにインデックスを更新するのが理想ですが、なかなか難しい問題です。まず、サーバ全体としてインデックスはスーパーユーザーだけが変更できるようにしておくべきなので、オペレーターを含む一般ユーザーでは変更できないというのが1点。さらにインデックスの再構築にはそれなりに時間がかかるので、あまり頻繁に更新すると失敗する可能性が高いという問題もあります。

 これを解決するには、cronを使って定期的にインデックスを更新するのがベターな解答でしょう。情報更新の頻度にもよりますが、普通のサーバなら1日1回更新すればよいのではないでしょうか。なぜなら、重要な変更はトピックスやWhat's Newsとして1週間程度はトップページからたどれるからです。

 LASER5 LinuxやDebian GNU/Linuxだと、/etc/cron.dailyの下にあるシェルスクリプトが、1日1回実行されます。ここに、

#!/bin/sh
LANG=ja_JP.ujis
export LANG
set PERL_BADLANG=0
export PERL_BADLANG
/usr/local/bin/mknmz -s --mhonarc --deny=".*.(pdf|z|[0-9][0-9]*)" -O /usr/local/var/namazu/index/Delphi /usr/share/public/www/Delphi

といった内容のシェルスクリプトを適当な名前(namazuなど)で作っておきます。もちろん、実行権を有効にしておくことを忘れずに。

(注)
画面サイズの都合により改行されていますが、スクリプトを作成する際は/usr/local/bin/mknmzから/www/Delphiまでを1行で入力してください。

 なお、mknmzコマンドを実行すると、削除されたファイルに対するインデックスは無効の印が付けられるだけで、データとしては残ったままです。これが度重なるとインデックスファイルが不必要に巨大化するので、たまに無効なインデックス情報を削除する必要があります。これに使うのがgcnmzコマンドで、引数としてインデックスを納めたディレクトリを指定します。これは週に一度、あるいは月に一度で十分かと思います。

Linux Square全記事インデックス


Linux & OSS フォーラム 新着記事
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Linux & OSS 記事ランキング

本日 月間