この文書では、Hyper Estraierのアプリケーションの詳細な使い方を説明します。イントロダクションをまだお読みでない場合は、先にそちらに目を通しておいてください。
Hyper Estraierは、いわゆるインデックス型の検索システムです。検索を行う前に、対象文書の情報を登録したインデックスを準備しておく必要があります。その手間がかかるかわりに、とても高速に検索を行うことができます。Hyper Estraierはインデックスを管理するコマンド「estcmd
」とインデックスを使って検索を行うCGIスクリプト「estseek.cgi
」からなります。つまり、コマンドラインでインデックスの管理作業を行い、Webブラウザで検索を行うことになります。
estcmd
は様々な形式の文書を扱うことができ、またインデックスに対する多様な管理操作を行うことができます。この文書では、文書の扱われ方やインデックスの管理方法について詳細に説明します。
Hyper Estraierは様々な検索方法をサポートします。複数の検索語を組み合わせたり、文書の属性を使って検索したりすることができます。また、estseek.cgi
の設定により、表示方法をカスタマイズすることができます。この文書ではそれらの方法についても説明します。
Hyper Estraierが扱う文書には、本文の情報だけでなく、タイトルなどの属性情報をつけることができます。属性は様々な応用ができます。属性を使った検索もできますし、更新日時の属性は差分更新の判断にも使われます。
属性には名前がつけられます。属性名は自由につけることができるのですが、Hyper Estraierが標準的に使う属性はシステム属性として予め定義されています。システム属性の名前には「@
」が先頭につきます。システム属性は以下のものがあります。
システム属性以外の属性はユーザ定義属性と呼ばれます。後述の文書ドラフト形式を使うと、任意のシステム属性とユーザ定義属性をつけることができます。HTMLのmeta要素やMIMEのヘッダもユーザ属性として扱われます。属性名は「%
」で始まってはいけません。
属性には2種類の型があります。文字列型と数値型です。文字列型は、任意の文字列です。文字列型の値には、完全一致、前方一致、後方一致、部分一致の判定ができます。数値型は、数値または日付の情報を表したものです。数値型は文字列を数値に直した上で、大小の判定が行われます。数値型の値は形式によって扱われ方が違います。日付として解釈される場合、UNIX紀元(1970年1月1日0時0分0秒)からの経過秒数が判定に使われます。
属性がどの型であるかは登録時には決定されません。検索時に属性をどちらの型として解釈するが指定されます。属性の長さに制限はありません。
文書の属性や本文に指定する文字列はUTF-8で表現されている必要があります。テキストファイルやHTMLなどでそれ以外の文字コードを使っている場合は、UTF-8に変換してください。なお、estcmd
は文字コードを自動判定して変換処理を行います。
システム属性でもユーザ属性でも、実際にどのような値を入れるかはユーザやアプリケーションに任されます。指定する側と解釈する側で合意が取れていれば問題ないわけですが、RFCなどで関連する規定がある場合はそれに従うのがよいでしょう。例えば、「@type
」にはRFC2045のメディアタイプの書式を用い、「@lang
」にはISO639の言語コード(「ja」「en」など)を用いるとよいでしょう。ユーザ属性の仕様を決める際にはDublin Coreの規格を参考にするといいかもしれません。
URI(Uniform Resource Identifier)は、文書を識別するための文字列です。HTTPやFTPやLDAPのURL(Uniform Resource Locator)はURIの一種です。インデックスに登録する全ての文書にはURI属性がついている必要があります。
外部(インターネット)に公開されるURIは、世界中のどのユーザからも一意に識別できる必要があります。したがって、ローカルホストでしか通用しない「file://
」のURLは外部に公開すべきではありません。estseek.cgiは「file://
」のURLを「http://
」や「ftp://
」などに置換する機能を備えていますので、それを活用してください。
URIはファイルを識別するだけのものではありません。書籍のISBNなどのURN(Uniform Resource Name)もURIの一種です。また、URIのスキーマは独自に定義することもできます。例えば、XYZ社の社員名簿の全文検索システムであれば、社員番号を含めた「xyz:empno:12345
」のようなURI属性を生成するのもよいでしょう。
URIに日本語などのマルチバイト文字をそのまま使ってはいけません。その場合、一般にURLエンコードと呼ばれるエスケープ処理が必要となります。URIの仕様についてはRFC3986を参照してください。
estcmdは、「file://
」で始まるローカルファイルシステムのURLをURI属性として自動的につけてくれます。ただし、対象文書がURI属性を独自に定義している場合はそちらを優先します。ローカルファイルシステムのURLは「_lpath
」という属性としても記録されます。ローカルファイルシステムの絶対パスは「_lreal
」という属性として記録され、ファイル名は「_lfile
」という属性として記録されます。各属性値の文字コードはUTF-8に正規化されます。「_
」で始まる名前の属性は、estseek.cgi
の詳細表示機能で表示されません。
ダイジェストとは、2つのデータが同じものかどうかを効率的に判定するために、データそのものの代わりに使われる短いデータです。メッセージダイジェストとも言います。インデックスに登録する全ての文書には、ダイジェスト属性が付加されます。
文書がダイジェスト属性を明示的に指定していない場合は、本文のMD5(Message Digest 5)を値とするダイジェスト属性が暗黙的に付加されます。明示的に指定する場合、MD5以外のアルゴリズムを使っても構いませんし、本文以外のデータ(ファイルそのものなど)を対象としてダイジェストを計算しても構いません。本文に更新があったならばダイジェストも変化するということが唯一の要件です。
estcmd
が扱う4種類のファイル形式のそれぞれがどのように扱われるかを説明します。その他の形式を扱うためのフィルタについては後述します。
特に構造のない文字列です。デフォルトでは、ファイル名の接尾辞が「.txt
」「.text
」「.asc
」の場合にプレーンテキストとして扱われます。
言わずもがな、Webで使われるハイパーテキストです。デフォルトでは、ファイル名の接尾辞が「.html
」「.htm
」「.xhtml
」「.xht
」の場合にHTMLとして扱われます。
隠しテキストについては後述します。
RFC822に基づくメッセージ交換のためのデータ形式です。デフォルトでは、ファイル名の接尾辞が「.eml
」「.mime
」「.mht
」「.mhtml
」の場合にMIMEとして扱われます。
マルチパートの各パートの中身が「text/plain」か「text/html」か「message/rfc822」の場合には、その内容を本文として扱います。これによって、Webアーカイブ(MHTML)も適切に扱うことができます。ヘッダの値がMIMEエンコードされていた場合はそれをデコードして扱います。エンティティがBase64やquoted-printableでエンコードされていた場合はそれをデコードして扱います。
文書ドラフトは、Hyper Estraier独自のデータ形式です。文書ドラフトを中間フォーマットとして使うことで、様々な形式の文書を統合的に扱うことができます。デフォルトでは、ファイル名の接尾辞が「.est
」の場合に文書ドラフトとして扱われます。
文書ドラフトの形式はRFC822に似ていますが、細かい違いがあります。ヘッダの区切り文字は「:
」でなく「=
」です。また、「=
」の後に空白を置く必要はありません。例えば、MIDIの歌詞データを登録する際には、以下のようなデータになるでしょう。
@uri=http://www.music-estraier.com/mididb/w/wa/wakamonotachi.kar @title=若者たち @author=佐藤勝,藤田敏雄 @cdate=2004-11-01T23:11:18+09:00 @mdate=2005-03-21T08:07:45+09:00 category=chorus,j-pop 君の行く道は 果てしなく遠い だのになぜ 歯をくいしばり 君は行くのか そんなにしてまで 若者たち 佐藤勝,藤田敏雄
文書ドラフトは以下の仕様を満たす必要があります。
属性部において、「%」で始まる行は制御命令とみなされて無視されます。文書ドラフトに別の目的のデータを混入させたい場合はこの機能を利用してください。
隠しテキストは、通常の本文と同様に検索語が抽出されますが、検索結果のスニペットでは表示されないことが特徴です。タイトルや著者に含まれる語も全文検索の対象にしたい場合には、タイトルや著者と同じ文字列を隠しテキストとしても指定するとよいでしょう。
文書ドラフトの最大の特徴は、URI属性を指定できることです。つまり、文書ドラフト自体のURIではなく、別のファイルのURIをインデックスに記録することができるのです。WebからHTMLデータを収集して文書ドラフト形式で保存するプログラムを作れば、簡易的なWeb検索エンジンを簡単に実現することができます。文書ドラフトを保存するオーバーヘッドをかけたくない場合は、いよいよAPIを使うことになります。
検索条件には、全文検索条件と属性検索条件の2種類があります。両方を同時に指定することもでき、その場合は両方を満たした文書が該当とみなされます。さらに、全文検索の条件式には、通常書式と簡便書式の2種類があります。用途に応じて使い分けてください。
全文検索条件式は、指定した語句が本文に含まれる文書を検索するためのものです。例えば、「コンピュータ
」という文字列を含む文書を探したいなら、検索式に「コンピュータ
」とそのまま指定してください。
複数の検索語を空白で区切ってならべることもできます。例えば、「United Nations
」と指定すると、「United
」の直後に「Nations
」が来る文書を検索します。
検索語を「AND」で挟んで並べると、AND検索ができます。例えば、「インターネット AND セキュリティ
」と指定すると、「インターネット
」と「セキュリティ
」の両方を含む文書を検索します。
検索語を「ANDNOT」で挟んで並べると、ANDNOT検索ができます。例えば、「スキー ANDNOT スノボー
」と指定すると、「スキー
」を含むが「スノボー
」は含まない文書を検索します。ANDNOT検索は、探したい語が他の語の一部に含まれてうまく検索できない場合にも便利です。「ファイル
」で検索すると「プロファイル
」がヒットして鬱陶しい場合には、「ファイル ANDNOT プロファイル
」とするとよいでしょう。
検索語を「OR」で挟んで並べると、OR検索ができます。例えば、「レモン OR ライム
」と指定すると、「レモン
」と「ライム
」の片方または両方を含む文書を検索します。OR検索は、類義語や表記の揺れに対応した検索をするのに便利です。「woman OR women
」などとして英単語の活用を吸収したり、「龍馬 OR 竜馬
」などとして漢字表記の揺れを吸収したりするとよいでしょう。
「OR
」は「AND
」や「ANDNOT
」よりも優先順位が高いことに注意してください。例えば、「F1 OR F-1 OR Formula One AND 優勝 OR チャンピオン
」と入力した場合、「F1
」か「F-1
」か「Formula One
」のどれかを含んで、かつ「優勝
」か「チャンピオン
」のどちらかを含む文書を探します。
Hyper Estraierは、日本語だけでなく、英語、ドイツ語、フランス語、中国語など、大抵の言語を扱うことができます。英字の大文字と小文字の違いは無視されます。「Japan
」「japan
」「JAPAN
」「jaPaN
」は全て同じです。ダイアクリティカルマーク付きのラテン文字や、ギリシア文字、キリル文字でも同様です。
「AND
」「ANDNOT
」「OR
」は演算子ですので、大文字で書かなければなりません。また、前後に空白が必要です。「AND
」という文字列を含む文書を探したい場合は、「and
」と指定してください。「ANDNOT
」や「OR
」でも同様です。
全ての文書に該当するワイルドカードとして、「[UVSET]
」という定数があります。これを使うと、純粋なNOT検索ができます。例えば、「[UVSET] ANDNOT ファイル
」とすると、「ファイル
」を含まない全ての文書を検索します。ただし、この処理は遅いです。
欧米に見られる空白で語を区切る言語の単語に対しては、前方一致または後方一致の条件を指定して検索を行うことができます(日本語には効果がありません)。前方一致の場合は文字列の前に空白を挟んで「[BW]」を置き、後方一致の場合は文字列の前に空白を挟んで「[EW]」を置きます。例えば、「[BW] euro
」だと「euro
」で始まる単語を含む文書を検索します。「[EW] sphere
」だと「sphere
」で終わる単語を含む文書を検索します。
Googleなどの検索エンジンでは、空白で区切ることでAND条件を指定できます。そのような挙動の方が望ましい場合は、簡便書式を使うことができます。簡便書式を使うかどうかは、アプリケーションのコマンドラインのオプションや設定ファイルで指定します。estseek.cgi
のデフォルトの設定では、簡便書式が使われるようになっています。
簡便書式では、空白または「&
」で区切るとAND条件になります。例えば、「インターネット セキュリティ
」と入力すると、「インターネット
」と「セキュリティ
」の両方を含む文書を検索します。
複数の検索語を「""」で括ると、フレーズ検索ができます。例えば、「"United Nations"
」と入力すると、「United
」の直後に「Nations
」が出現する文書を検索します。
「!」を使うとNOT検索ができます。例えば、「スキー ! スノボー
」と入力すると、「スキー
」を含むが「スノボー
」を含まない文書を検索します。
「|」を使うとOR検索ができます。例えば、「レモン | ライム
」と入力すると、「レモン
」か「ライム
」の片方または両方を含む文書を検索します。
「|
」の優先順位が「&
」や「!
」より高いのは通常書式と同じです。
簡便書式においては、ワイルドカードによって前方一致や後方一致の条件を指定することができます(日本語には効果がありません)。前方一致の場合は文字列の後に「*」を置き、後方一致の場合は文字列の前に「*」を置きます。例えば、「euro*
」だと「euro
」で始まる単語を含む文書を検索します。「*sphere
」だと「sphere
」で終わる単語を含む文書を検索します。
空白や「&」「!」「|」「*」を検索語そのものとして指定したい場合は、フレーズ検索を応用してください。例えば「AT&T」を検索したい場合は、「"AT&T"」とします。
属性検索条件式は、各文書が持つ属性に対して演算子を適用して、該当する文書を検索するためのものです。属性条件式は属性名と演算子と値を空白で区切って並べたものです。例えば、「@title STRINC 重要
」と指定すると、タイトルに「重要
」という文字列を含む文書だけに絞り込みます。「STRINC
」は演算子です。属性検索用の演算子には以下のものがあります。
演算子の前に「!」を置いて「!STREQ
」などとすると、条件に当てはまらないものに絞り込みます。例えば、「@title !STRBW ※未承諾広告
」などとします。文字列の演算子の前に「I」を置いて「ISTREQ
」などとすると、文字列の大文字と小文字の違いを無視します。「!
」と「I
」を両方指定する場合、「!ISTREQ
」などとします。演算子を省略して属性名のみを指定した場合、値は問わずに、その属性を備える文書を該当とみなします。
属性条件は複数指定することができます。その場合、指定された全ての条件を満たす文書が該当とみなされます。なお、属性検索を行うと候補の全ての文書の情報を参照するため、検索速度が多少遅くなります。
順序指定式によって、結果の表示順序を指定することもできます。順序指定式は属性名と演算子を空白で区切って並べたものです。例えば、「@size NUMA
」と指定すると、サイズが小さい文書から並べられます。「NUMA
」は演算子です。順序指定用の演算子には以下のものがあります。演算子を省略した場合は、「STRA
」が指定されたとみなします。
順序指定を行わなかった場合は、スコアの降順になります。スコアとは、各文書に指定した検索語がどのくらい含まれるかという指標です。AND検索やOR検索で複数の語が指定された場合、TF-IDF法に基づいてスコアの調整が行われます。「the
」や「する
」といった頻出語よりも、「hippopotamus
」や「咀嚼
」といった特徴的な語句に高いスコアをつけるということです。また、検索語が同数程度含まれるならば、総語数の多い文書よりも総語数の少ない文書の方がスコアが高くなります。
順序指定式は一つしか指定できません。なお、順序指定を行うと候補の全ての文書の情報を参照するため、検索速度が多少遅くなります。
ある文書に似た文書を探す、類似検索式もサポートされます。関連文書検索とも呼ばれることもあります。類似検索の利用方法はアプリケーションによって様々ですが、典型的には、検索結果に示される文書のひとつをユーザが指定して、それに似た文書を再検索するために使われます。類似検索の結果は類似度の降順に並べられます。類似度はベクトル空間モデルという考え方に基づいて算出されます。文書からキーワードを取り出してベクトルとして表現し、ベクトル同士のなす角の余弦を類似度とするものです。ちょっと難しい言い方になりましたが、要するに、語彙が似通った文書は類似度が高くなるということです。キーワードとしては、文書内の頻度にTF-IDF法で重みづけを行った結果が上位の語句が選択されます。
類似検索式をユーザが入力する必要はありませんが、アプリケーションに類似検索機能をつけるためには書式を知っておく必要があります。検索フレーズが「[SIMILAR]」という演算子で始まっている場合に類似検索が行われます。「[SIMILAR]
」の後ろには、種文書(類似判定の元となる文書)のベクトルの要素を列挙します。各要素は「WITH」演算子で始まり、スコアの数値とキーワードの文字列を空白で区切って指定します。例えば、300
の「日本
」と250
の「japan
」と100
の「東京
」を含む文書を仮想の種文書とする場合は、「[SIMILAR] WITH 300 日本 WITH 250 japan WITH 100 東京
」と指定します。
関連文書検索と順序指定式を同時に指定した場合、類似度が0.5以上の文書に絞り込んだ上で、順序指定式に基づいて並べられます。なお、関連文書検索の検索速度はとても遅いです。
検索結果に似たような文書ばかりが並んで鬱陶しい場合は、類似隠蔽機能を利用してください。類似隠蔽機能のインターフェイスはアプリケーションによって異なりますが、0.0から1.0までの類似度を指定します。すると、検索結果の各々の文書に対して、指定した値を越える類似度を持つ他の文書を重ねる処理を行います。重なった文書群の中で表示されるのは最も順位の高いものだけです。類似度の指定は0.7から0.9までの間にすると使いやすいでしょう。
検索フレーズが「[ID]」で始まっている場合にはID検索が行われます。指定したID番号の文書のみが該当します。例えば、「[ID] 5
」のようにします。検索フレーズが「[URI]」で始まっている場合にはURI検索が行われます。指定したURIの文書のみが該当します。例えば、「[URI] http://estraier.gov/foo.html
」のようにします。これらによって、検索コマンド(estcmd search
)を取得コマンド(estcmd get
)の代用として使うことができます。
文書の本文や検索フレーズの文字列から検索語を抽出する際には、いくつかのルールがあります。ここでは、そのルールついて詳しく説明します。
英語やその他のヨーロッパの言語にのように空白で語が区切れる場合、空白で区切った文字列を検索語として登録します。「It is fine today.
」という文字列からは、「it
」「is
」「fine
」「today
」「.
」の5個の検索語が抽出されます。
日本語をはじめとする、語を空白で区切れない言語の場合は、N-gramという手法で検索語が抽出されます。連続するN文字を語として、1文字ずつずらしながら語を抽出する手法です。Hyper Estraierでは2文字を語とするので2-gram(bi-gram)と呼ばれることもあります。例えば「本日は晴天なり。」という文字列からは、「本日
」「日は
」「は晴
」「晴天
」「天な
」「なり
」「り。
」の7個の検索語が抽出されます。
2-gram方式だと1文字の検索語はどの検索キーにも一致しないことになりますが、それでも検索は可能です。1文字の検索語が指定された場合、その文字を含む全てのキーのOR検索が内部的に行われます。ただし、調べるキーの数が多いので、検索速度は少し遅くなります。
「ホンマグロ
」という検索語が指定された場合「ホン
」「ンマ
」「マグ
」「グロ
」を含み、かつそれぞれが隣り合っている部分がある文書を該当とみなせばよいことになります。しかし、デフォルトでは全ての語をの検査をせず、「ホン
」と「マグ
」だけを調べます。「ホン」の1つ飛ばした隣に「マグ
」があるならば、「ンマ
」を調べる必要はないからです。また、各検索語は後ろになにが来るかという情報を持っているので、「マグ
」を調べると「グロ
」の存在もわかります。このような工夫をしてなるべく検査を省略した方が、応答時間が短くなって快適です。
ただし、スコアの計算は、調べた検索語が各該当文書の中で出現する数を基準に行うので、全ての語を調べた方が精度が高まることが多いです。つまり、速度と精度のトレードオフの関係になります。どちらを優先するかはアプリケーションのコマンドラインオプションや設定ファイルで指定します。estseek.cgi
のデフォルトの設定では1個飛ばしで検査するようになっています。
Hyper Estraierでは、N-gramの連接判定の精度を落とすことによって処理速度を上げる工夫がなされています。検索やインデックス更新の処理が高速な反面、まれに検索語が含まれない文書が該当とみなされることがあります。検索語の後ろ2語まで(日本語なら3文字分)の連接判定しかしませんので、「シミュレーション
」で検索した場合、「シミュレ
」「ミュレー
」「ュレーシ
」「レーショ
」「ーション
」の全てを含む文書は、たとえ「シミュレーション
」がなくても該当してしまいます。また、連接判定にはハッシュ関数を用いますので、まれ(251分の1の確率)に精度が3語分を下回ることがあります。
ただし、スニペットを作る際には文字列の逐次探索による完全な連接判定が行われますので、スニペットの中に検索語のハイライトが含まれない文書は検索ゴミであることが容易にわかります。なお、estseek.cgi
には、検索ゴミであることを検出して表示しないようにするオプションもあります。
N-gram方式と対比されるアプローチとして、分かち書き方式があります。自然言語の文法や語法に基づく方法で単語や形態素を切り出すものです。Hyper Estraierの前身であるEstraierでは分かち書き方式を採用していました。N-gram方式は再現率がほぼ完璧である(検索漏れがない)という利点がありますが、分かち書き方式に比べて精度が低い(検索ゴミが多い)という欠点があります。検索システムの用途や対象文書の内容によってどちらが適するかは変わってきます。興味を持たれた方は、Hyper EstraierとEstraierの使い勝手を比べてみてください。
ここでは、インデックス管理用コマンドestcmd
の詳細な仕様を説明します。検索もできるので、estcmd
をスクリプト言語から呼び出せばそれなりのアプリケーションが簡単に作れます。
estcmdは多くのサブコマンドの集合体です。サブコマンドの名前は第1引数で指定されます。その他の引数はサブコマンドの種類に応じて解釈されます。dbという引数はインデックスのパスです。
全てのサブコマンドは、処理が正常に終了した場合には0を、そうでない場合は1を終了ステータスにします。put
、out
、gather
、purge
、randput
、wicked
、regression
については、実行中のプロセスに1(SIGHUP)、2(SIGINT)、3(SIGQUIT)、13(SIGPIPE)、15(SIGTERM)のどれかのシグナルを送ることにより、データベースを閉じて正常終了させることができます。
gather等の「-ic
」オプションでは、「UTF-8
」「EUC-JP
」「Shift_JIS
」「ISO-2022-JP
」「ISO-8859-1
」などの、IETFに登録されている文字コード名を指定してください。実際には、iconvが認識する名前は全て使えます。また、「-il
」オプションでは、「en
」(英語)、「ja
」(日本語)、「zh
」(中国語)、「ko
」(朝鮮語)のどれかを指定してください。
gatherの「-fx
」オプションで指定した外部コマンドは、第1引数に対象文書のパス、第2引数に出力先のパスが渡されて呼び出されます。すなわち、外部コマンドは第1引数のファイルを解析して文書ドラフトやプレーンテキストやHTMLやMIMEを生成し、第2引数のファイルに書き込むという機能を持つことが期待されます。なお、対象文書は一時ファイルとしてコピーされて渡されます。対象文書の元来のパスは環境変数ESTORIGFILE
の値として渡されますが、決して元のファイルを変更してはいけません。ESTORIGFILE
を使う場合はファイルを読み込む必要はありませんので、「-fo
」オプションも同時につけるとよいでしょう。
mh形式(1メール=1ファイル)でメールボックスを管理するメーラ(Mew、Wanderlust、Sylpheedなど)をお使いなら、個々のメールを対象にした全文検索のインデックスを簡単に作ることができます。例えば、メールボックスが「/home/mikio/Mail」にあり、その中のbusinessフォルダかfriendsフォルダに振り分けられたメールを登録する場合、以下のコマンドを実行します。
find /home/mikio/Mail -type f | egrep 'inbox/(business|friends)/[0-9]+$' | estcmd gather -cl -fm -cm casket -
作成されたインデックスは、estseek.cgi
を使って検索することができます。なお、-cm
オプションをつけておくことで、差分更新ができます。MIMEにはDateヘッダがありますので、-sd
オプションでファイルの更新時刻を持ってくる必要はありません。
mh形式以外のメーラをお使いの場合は、mh形式になるようにメールをエクスポートしてください。Windowsで言うところのEML形式でも構いません。あるいは、APIを使って専用のアプリケーションを作成してください。
外部コマンドをフィルタとして呼び出すこともできます。「/usr/local/share/hyperestraier/filter/
」に各種のフィルタがインストールされているので、適宜ご利用ください。
estfxmantotxt
はUNIXのman
のマニュアルをプレーンテキスト形式に変換するフィルタです。以下のように利用して、man
のファイルを対象にしたインデックスを作ることができます。
PATH=$PATH:/usr/local/share/hyperestraier/filter ; export PATH find /usr/share/man /usr/local/man -type f | egrep '.*/man[0-3]/.*\.[0-3](.gz)*$' | estcmd gather -cl -fx ".1,.2,.3,.1.gz,.2.gz,.3.gz" "T@estfxmantotxt" -fz -sd -cm casket -
estfxmsotohtml
はMS-Office(Word/Excel/PowerPoint)のファイルをHTML形式に変換するフィルタです。以下のように利用して、MS-Officeのファイルを対象にしたインデックスを作ることができます。なお、estfxmsotohtml
を動作させるにはwvWare(wv-1.0.3)とxlhtml(ppthtmlも同梱)をインストールしておくことが必要です。
PATH=$PATH:/usr/local/share/hyperestraier/filter ; export PATH estcmd gather -cl -fx ".doc,.xls,.ppt" "H@estfxmsotohtml" -fz -ic UTF-8 -sd -cm casket .
estfxpdftohtml
はPDFのファイルをHTML形式に変換するフィルタです。以下のように利用して、PDFのファイルを対象にしたインデックスを作ることができます。なお、estfxpdftohtml
を動作させるにはpdftohtml
をインストールしておくことが必要です。
PATH=$PATH:/usr/local/share/hyperestraier/filter ; export PATH estcmd gather -cl -fx ".pdf" "H@estfxpdftohtml" -fz -ic UTF-8 -sd -cm casket .
各フィルタの中身を見ていただければ、とても簡単なシェルスクリプトであることがお分かりいただけると思います。シェルやPerlやRuby等で同様のプログラムを書けば様々なフィルタを簡単に作ることができます。ただし、外部コマンドのフィルタは呼び出しのオーバーヘッドが大きいので、大量の文書を扱うのには向いていません。本格的にやるならばAPIを使ってください。
コマンドラインから検索する際には、端末の文字コードを考慮する必要があります。例えば端末の文字コードがEUC-JPの場合は、以下のようにするとよいでしょう。
estcmd search -ic EUC-JP -vh -max 8 casket 'こんにちは' | iconv -f UTF-8 -t EUC-JP -c | less
-ic
オプションで検索式の文字コードを指定して、iconvで出力の文字コードを変換しています。-vh
オプションと-max
オプションは検索結果を見やすくするためにつけています。上述の検索語を可変にしたスクリプトを作っておくと便利かもしれません。
各種のスクリプト言語からHyper Estraierの検索結果を手軽に利用するためには、estcmd
のXML出力機能を用いるとよいでしょう。XMLの詳しい書式についてはestresult.dtd
をご覧ください。
estcmd search -vx -max 8 casket 'socket AND shutdown'
ここでは、検索用CGIスクリプトestseek.cgi
の詳細な仕様を説明します。設定ファイルの書き方が中心になります。
estseek.cgi
が動作するには、設定ファイルとテンプレートファイルとトップページファイルが必要です。それぞれestseek.conf
、estseek.tmpl
、estseek.top
というのが標準的な名前です。
設定ファイルの名前はCGIスクリプトの接尾辞を.conf
に変えたものです。estseek.cgi
をestsearch.cgi
という名前に変えたとしたら、estsearch.conf
が読み込まれます。テンプレートファイルとトップページファイルの名前は設定ファイルの中で記述されますので、同一ディレクトリの中にいくつもの検索用ページを設置することができます。
estseek.cgi
は「/usr/local/libexec/estseek.cgi
」としてインストールされていますので、それをコピーして利用してください。また、設定ファイルなどのサンプルが「/usr/local/share/hyperestraier/
」の中にインストールされていますので、それをコピーして修正すると楽です。「/usr/local/share/hyperestraier/locale/ja/
」の中には日本語化されたサンプルもあります。
設定ファイルは、変数名と値を「:
」で区切った形式の行を並べたものです。デフォルトでは、設定ファイルは以下のような内容になっています。
indexname: casket tmplfile: estseek.tmpl topfile: estseek.top logfile: lprefix: file:///home/mikio/public_html/ gprefix: http://localhost/ gsuffix: dirindex: index.html replace: //localhost/{{!}}//127.0.0.1/ replace: //127.0.0.1:80/{{!}}//127.0.0.1/ showlreal: false perpage: 10,20,30,40,50,100 attrselect: false showscore: false extattr: author|Author extattr: from|From extattr: to|To extattr: cc|Cc extattr: date|Date snipwwidth: 480 sniphwidth: 96 snipawidth: 96 condgstep: 2 dotfidf: true scancheck: false smplphrase: true candetail: true smlrvnum: 0 spcache:
それぞれの変数の機能を以下に示します。
{{!}}
」で区切って指定します。複数回指定できます。true
」か「false
」です。true
」か「false
」です。true
」か「false
」です。|
」で区切って指示します。複数回指定できます。1
」だと全ての語を調べ、「2
」だと1個置き、「3
」だと2個置き、「4
」だと3個置きに調べます。true
」か「false
」です。true
」か「false
」です。true
」か「false
」です。true
」か「false
」です。lprefix
とgprefix
の関係は少しわかりにくいかもしれません。簡単に言えば、検索結果の各文書のURIから、lprefix
に前方一致する部分を削って、代わりにgprefix
の文字列を付加するという機能です。lprefix
、gprefix
、gsuffix
、dirindex
の処理の例を以下に示します。
replace
を指定すると、lprefix
、gprefix
、gsuffix
、dirindex
の処理を行った後に、さらに変換を行います。複数回指定できます。例えば、「.txt
」を「.html
」に変えたい場合は、以下のようにします。
.txt{{!}}.html
extattr
は任意の属性を表示するのに使います。複数回指定できます。例えば、文書の更新日時を「Modified
」というラベルをつけて表示したい場合は「extattr: @mtime|Modified
」と書き、文書のサイズを「Size
」というラベルをつけて表示したい場合は「extattr: @size|Size
」と書きます。
検索ページの見栄えを決めるためのファイルです。HTMLで、記述してある内容がそのまま表示されます。ただし、「<!--ESTFORM-->
」の部分には検索フォームが挿入され、「<!--ESTRESULT-->
」の部分には検索結果が挿入され、「<!--ESTINFO-->
」の部分にはインデックスの情報が挿入されます。CSSやJavaScriptを駆使すれば、かなり自由にユーザインターフェイスをカスタマイズすることができます。
検索用CGIスクリプトに最初にアクセスした際、あるいは検査条件を全く入力しないでアクセスした際に表示されるメッセージを記述したファイルです。記述してある内容が検索結果の位置にそのまま挿入されます。デフォルトでは検索機能の簡単な使い方が記述してありますが、システムのメンテナンス情報などを記載してもよいでしょう。
Webサイトの検索機能として設置する場合、サイトのトップページに検索フォームを置きたくなるでしょう。その場合、以下のようなHTMLを書いてください。
<form method="get" action="estseek.cgi"> <div> <input type="text" name="phrase" value="" size="32" /> <input type="submit" value="Search" /> <input type="hidden" name="enc" value="UTF-8" /> </div> </form>
「estseek.cgi
」の部分は設置したestseek.cgi
のURLにしてください。「UTF-8
」の部分はそのページの文字コードにしてください。「EUC-JP
」「Shift_JIS
」「ISO-2022-JP
」「ISO-8859-1
」などが使えます。
属性条件の入力欄に「gstep=1
」などとすると、N-gramの検査精度を一時的に変えられます。同様に「tfidf=true
」または「tfidf=false
」とすると、TF-IDF法の有効無効を一時的に変えられます。「scan=true
」または「scan=false
」とすると、検索フレーズの精密検査の有効無効を一時的に変えられます。
検索結果の経過時間表示の右側に「*
」マークがつくことがあります。これは、インデックス内に削除文書の情報がたくさんあることによって検索処理が非効率になったことを意味しています。頻繁にこれがでるようになったら、インデックスの最適化を行ってください。
ここでは、アプリケーションとしてのHyper Estraierを活用するためのコツをいくつか紹介します。
文書を登録する処理では、インデックスの内部で持っているデータベースに膨大な量の書き込みを行います。データベースを参照するオーバーヘッドを抑えるために、Hyper Estraierは処理中のデータをメモリ上にキャッシュする仕組みを持っています。キャッシュが大きい方が登録処理は高速になりますが、スワップが起きるとかえって効率が落ちますので、実メモリの4割程度の大きさにするとよいようです。例えば1GBの実メモリを搭載しているマシンで作業をする場合、400MB程度が適切でしょう。
estcmd
の-cs
オプションを使うとキャッシュサイズの指定ができます。サイズはメガバイト単位で指定します。デフォルトは64MBです。キャッシュサイズを400MBに指定するには、以下のようにします。
estcmd gather -cl -il ja -sd -cm -cs 400 casket .
インデックスの最大サイズはおおよそ300GBです。また、対象文書がプレーンテキストの場合、インデックスのサイズは対象文書の容量の50%から200%程度になります。HTMLであれば25%から100%程度です。したがって、一つのインデックスに登録できる文書の総量の目安は、プレーンテキストなら300GB、HTMLなら600GBといったところです。なお、インデックスのサイズは、小さい文書が多数あるよりも、大きい文書が少数ある方が小さくなります。また、日本語の文書よりも英語の文書の方が小さくなります。
インデックスを更新している最中にはロックがかかるので、そのインデックスを使った検索はその間はできなくなります。検索システムとしては、その間は停止時間ということになります。それを避けるためには、インデックスのコピーに対して更新を処理を行い、完了したらオリジナルと入れ換えるようにするとよいでしょう。また、インデックスの更新中に不意にシステムが停止するなどしてインデックスが壊れた場合も、複製に対する更新であれば問題がないので安心です。
上述の処理を自動化するには、以下のようなスクリプトを書いておくとよいでしょう。冒頭のexit文は、複製が既に存在している場合(以前の更新に失敗するとそうなります)に処理を停止するようにしています。途中のexit文では、更新したインデックスが壊れた場合に処理を停止するようにしています。
test -e /home/www/casket-copy && exit cp -R /home/www/casket /home/www/casket-copy /usr/local/bin/estcmd gather -il ja -sd -cm /home/www/casket-copy /home/www/public_html /usr/local/bin/estcmd purge /home/www/casket-copy /usr/local/bin/estcmd optimize /home/www/casket-copy /usr/local/bin/estcmd inform casket-copy || exit rm -rf /home/www/casket mv /home/www/casket-copy /home/www/casket
gather
やpurge
を実行する際に「-cl
」をつけるべきかどうかは運用の仕方によって変わってきます。「-cl
」をつけた場合は、転置インデックスを部分的に最適化するので、処理がやや重くなります。ただし、明示的にoptimize
を実行しなくても検索の速度や精度が落ちません。
「-cl
」をつけない場合は、転置インデックスを更新しないで、文書情報に削除マークをつけるだけですので、比較的に軽い処理で済みます。ただし、検索時に無駄な領域を処理することになりますので、検索の速度と精度が少しずつ落ちてきます。それを解消するために、定期的にoptimizeを実行することが必要となります。「-cl
」をつけないで削除した文書の領域を回収するには、optimize
以外の手段はありません。
通常の運用では、「-cl
」をつけてgather
やpurge
を実行するのがよいでしょう。ただし、とても大量の上書きや削除を行う場合には、「-c
l」をつけないでgather
やpurge
を実行してから、optimize
を実行する方が効率的です。また、可用性の確保の項目で述べたように、インデックスの複製に対して更新する場合にも「-cl
」をつけない方法が適します。optimize
をした方がインデックスが小さく保たれるからです。
estseek.conf
のsmlrvnum
を正の数にすると、estseek.cgi
で類似検索が可能になります。検索結果の各文書に「[similar]
」というリンクが表示されますので、それを選択すると、その文書を種文書とした類似検索が実行されます。なお、estcmd
の「-sim
」オプションを使うと、コマンドラインからでも類似検索ができます。
類似検索を実行すると、候補の各文書のキーワードを計算するので、とても時間がかかります。estcmd
のextkeys
サブコマンドを用いて予めキーワードのデータベースを作っておくと、類似検索の速度が劇的に向上します。キーワードの選択にはTF-IDF法を用いますので、インデックスを構築する最後の手順で行った方が精度が安定します。したがって、extkeys
を含めたインデックスの更新手順は以下のようになります。
estcmd gather -cl -il ja -sd -cm casket . estcmd purge -cl casket estcmd extkeys casket
キーワード用のデータベースはoptimize
を行うと消去されます。したがって、optimize
が必要な場合は、optimize
を先に実行してからextkeys
を実行してください。
estseek.conf
におけるsmlrvnum
の値はベクトル空間の次元数を意味しますが、32程度がお薦めです。増やすと精度が上がる代わりに速度が下がります。減らすと精度が下る代わりに速度が上がります。extkeys
を実行した場合には、その際の「-kn
」オプションの値が次元数の決定に使われます。
デフォルトでは、extkeysはTD-IDFのための文書頻度(DF)のデータを全てメモリ上に展開するので、搭載メモリが少ない環境ではメモリ不足になることが考えられます。その場合は、予めDFのデータを外部データベースに保存しておいて、それを使ってextkeysを実行するとよいでしょう。以下のようにしてください。
estcmd words -dfdb mydfdb casket estcmd extkeys -dfdb mydfdb casket
estseek.conf
で類似検索を有効にすると、類似隠蔽も有効になります。Googleがやっているように、似すぎた文書を表示しないようにするものです。「clip by x.x
」のところで指定した値以上の類似度の文書は表示されなくなります。類似検索が便利な場合はそれほどないかもしれませんが、類似隠蔽はほとんどの場合で便利です。一度使ったら手放せなくなることうけあいです。
プレーンテキストの文書や、HTMLの文書でmeta要素による文字コードの指定がなされていないものには、インデクシングの際に「-il
」オプションの言語指定に応じて文字コードが自動判定されます。しかし、自動判定の精度は完璧ではありません。自動判定の誤りによって文字化けが発生した際には、「-ic
」オプションで文字コードを明示するとよいでしょう。例えば、「/home/www/public_html/chinese
」以下の文書はEUC-CNで書かれていて、「/home/www/public_html/korean
」以下の文書はEUC-KRで書かれていることが分かっているならば、以下のようにします。
estcmd gather -cl -ic EUC-CN -sd -cm casket /home/www/public_html/chinese estcmd gather -cl -ic EUC-KR -sd -cm casket /home/www/public_html/korean estcmd gather -cl -sd -cm casket /home/www/public_html
Windows上で「Ⅲ
」「③
」「㌦
」などのいわゆる外字を使うことも多いかと思いますが、それらを含んだテキストをShift_JISとして扱うのは避けた方がよいでしょう。文字化けする可能性が高くなります。代わりにCP932もしくはWindows-31Jとして扱ってください。
日本語などのマルチバイト文字を含んだ名前のファイルを登録することもできますが、文字化けを防ぐためには文字コードを明示することが必要です。estcmd gather
の「-pc
」オプションを使います。例えばEUC-JPであると指定する場合は、以下のようにします。
estcmd gather -cl -pc EUC-JP -sd -cm casket .
UNIXではEUC-JPかUTF-8でファイル名を扱うことが多いです。日本語版のWindowsはCP932でファイル名を扱います。「-pc
」オプションの値にShift_JISを指定しても期待通りに動作しないことに注意すべきです。Shift_JISの「\
」(0x5c)をUTF-8に正規化すると、バックスラッシュでなく円マークになってしまい、区切り文字としての機能が失われるためです。CP932(Windows-31J)は「\
」をバックスラッシュとして扱うことが明示されている規格なので、この問題はありません。
検索結果の各文書のURIをファイルプロトコル(「file://」で始まるURL)の形式で表示する場合には、そのURIを選択した際の挙動がブラウザによって異なることに注意しなければなりません。
Mozilla FirefoxやNetscapeのデフォルトの設定では、ファイルプロトコルのURLをブラウズすることはできません。アドレスバーに「about:config
」と入力してから「security.checkloaduri
」の値を「false
」にする必要があります。
Microsoft Internet Explolerは、URLエンコードをデコードして得られた文字列の文字コードとURIが置かれているページの文字コードが同一であると仮定し、それに基づいてローカルにおける標準の文字コードに正規化を行った上でリソースを探します。したがって、Shift_JISのファイル名をエンコードして得られたURIは、estseek.cgi
が出力するUTF-8のページに置くことができません。対策としては、別のブラウザを使うか、日本語のファイル名を使わないようにするか、ファイルプロトコルの代わりにHTTPを使うことが考えられます。
SMBのファイルサーバの文書を対象としてWindowsに閉じた環境で利用する場合は、URIの代わりにUNC(Universal Naming Convention)をリンク先にすると便利です。estseek.conf
にある「showlreal
」の値を「true
」にすると、エンコードされたURIの代わりに、対象文書のファイルの絶対パスが使われます。この絶対パスにはURIエンコードが施されず、仮名や漢字がそのまま含まれます(これはHTMLの規格に違反しますが)。これを「lprefix
」や「gprefix
」によってUNCに加工してください。なお、UNCにドライブ文字を含めてはならないということに注意してください。例えば、「d:\pub
」が「\\skyhigh\pub\
」として共有されているなら、estseek.conf
に以下のような設定をします。
... lprefix: d:\pub\ gprefix: \\skyhigh\pub\ gsuffix: dirindex: showlreal: true ...
Windows用のバイナリパッケージには、xdoc2txt
というフィルタプログラムが同梱されています。これをHyper Estraierから呼び出すためのestxfiltというラッパーも同梱されています。それらを使うと、PDF、RTF、MS-Word、MS-Excel、MS-PowerPointなどのファイルをインデックスに登録できます。同梱のコマンドとDLLは全てパスの通った場所に置いてください。
例えば、「D:\mikio\doc
」以下のファイルを登録したインデックスを作成するには、以下のようなコマンドを実行します。
cd D:\mikio\doc estcmd gather -cl -fx .pdf,.rtf,.doc,.xls,.ppt T@estxfilt -fz ^ -ic CP932 -pc CP932 -sd -cm casket .
「-ic
」オプションでCP932を指定しているのは、estxfilt
の出力の文字コードがCP932であるとわかっているためです。なお、行末の「^
」はコマンドプロンプトのエスケープ文字です。
gather
の「-fx
」オプションで呼び出されるフィルタプログラムは、好きなように実装することができます。プログラム言語は何でも構いません。第1引数で指定されるファイルを読み込んで、第2引数のファイルに書き込めばよいのです。出力の形式は、文書ドラフト、プレーンテキスト、HTML、MIMEから選択することができます。
例えば、MP3のファイルからタイトル等の情報を抜き出すフィルタを考えてみましょう。標準シェルで実装して、mp3infoとiconvを組み合わせることにします。なお、ID3タグの文字コードがISO-8859-1(Latin1)であることを前提としていますが、これは実際に記録している文字コードに合わせて読みかえてください。
#! /bin/sh mp3info -p '@title=%t\n@author=%a\n@type=audio/mpeg\n\n%c\n\t%t\n\t%a\n' "$1" | iconv -f ISO-8859-1 -t UTF-8 < "$2"
上記を「estmp3todraft
」という名前で保存して、実行権限をつけて、パスの通った場所に置きます。あとは、以下のコマンドを実行すれば、MP3ファイルをインデックスに登録することができます。
estcmd gather -cl -fx .mp3 estmp3todraft -fz -sd -cm casket .
各種のフィルタが充実すると多くのユーザに喜んでいただけるので、もしあなたが有用なフィルタを作ったなら、Hyper EstraierのMLにぜひ紹介してください。
属性検索条件や順序指定の式を手入力するのが面倒な場合、estseek.conf
のattrselect
属性をtrueにしてください。セレクトボックスで指定できるようになります。
任意のユーザ属性を表示したいなら、estseek.conf
のextattr
属性を利用してください。
入力フォームを変更したいなら、estseek.tmpl
の中の "<!--ESTFORM-->
" の代わりに自分でフォームのHTMLを書いても構いません。その他、JavaScriptやCSSを駆使すればばかなりのカスタマイズができるはずです。
CSSやJavaScriptでできないカスタマイズが必要ならば、estseek.c
のソースを書き換えて改造してもよいですし、estcmd
のXML出力モードを呼び出すスクリプトを書いてもよいでしょう。もちろん、APIを使ったプログラミングをすれば、最も強力なアプリケーションを作ることができるでしょう。
入力フィールドに文字を打ち込む毎に結果の画面が更新される、いわゆるインクリメンタル検索を行うこともできます。それには、以下の手順を実行してください。
-apn
オプションは、完全N-gram方式のデータベースを作ることを指示します。完全N-gram方式とは、ヨーロッパ系の言語を解析する際にもN-gram方式を適用するものです。この指示はデータベースを作成する時にしかできません。データベースを作成した後に方式を変更することはできないということです。完全N-gramでなくてもインクリメンタル検索は可能ですが、英文だと単語毎でしか文書がヒットしないので多少不便になります。なお、完全N-gram方式の欠点は、インデックスのサイズが大きくなることと、関連文書検索の精度が下がることです。したがって、インクリメンタル検索を使わない場合は通常の方式が推奨されます。
裏技の範疇に入りますが、estseek.cgi
を高速化したプログラムを作ることが可能です。これはUNIX版のみの機能で、FastCGIという規格に基づくものです。FastCGIの実行環境(mod_fcgiなど)とライブラリ(libfcgi)をインストールした上で、Hyper Estraierのソースパッケージの中で「make fcgi
」を実行してください。すると「estseek.fcgi
」というプログラムが作成されます。これをestseek.cgiの代わりに利用してください。
FastCGIスクリプトはCGIスクリプトとほぼ同じインターフェイスでありながら、常駐プロセスになることが特徴です。したがって、プロセスを複製したりDBに接続したりするオーバーヘッドがかからないので、応答時間がかなり短くなります。同時接続数が多いサイトではこの方法はオススメです。FastCGIの詳細についてはFastCGIのホームページをご覧ください。
estseek.fcgi
はインデックスをロックし続けるので、Webサーバの稼働中はインデックスを更新することができません。インデックスを更新するためには、estcmd
で更新命令を掛けてから、Webサーバを再起動することになります。以下のようにするとよいでしょう。
estcmd gather -cl -il ja -sd -cm casket . & sudo /usr/local/apache2/bin/apachectl restart
スペシャルキャッシュとは、特定の属性の値をキャッシュすることによって処理の高速化を図る仕組みです。estseek.conf
のspcache
はスペシャルキャッシュの属性名を指定します。例えば、更新日時によるソートを頻繁に行う場合は、@mdate
属性を指定しておくとよいでしょう。スペシャルキャッシュの対象に指定できる属性はひとつだけです。スペシャルキャッシュはメモリ上のキャッシュですので、CGIでは機能しません。常駐プロセスであるFastCGIでのみ威力を発揮します。
NFSマウントのファイルシステム上にインデックスを置く場合には若干の注意が必要です。まず、そのNFSサーバおよびNFSクライアントがロックをサポートしている必要があります。21世紀の実装であれば大抵はロックをサポートしているでしょう。また、NFSサーバのプロセッサとNFSクライアントのプロセッサのエンディアンが一致していることが必要です。
以上の条件を満たしているならば、NFSを使って複数のマシンでインデックスを共有することができます。並列化に関する条件は単一のマシンを使っている場合と同じです。すなわち、あるプロセスがライタで接続している間は他のプロセスはリーダでもライタでも接続できず、あるプロセスがリーダで接続している間は他のプロセスはリーダであれば接続できます。
プロクシサーバWWWOFFLEのキャッシュを対象とした検索システムを構築することも簡単です。そのために、WWWOFFLEのキャッシュのリストを出力するコマンドとして `estwolefind
' が提供されます。これは、第1引数で指定したディレクトリにあるWWWOFFLEのキャッシュファイルのパスとそれに対応するURLおよびファイル名をTSV形式で出力するものです。
例えば、WWWOFFLEのキャッシュが「/var/spool/wwwoffle
」にあるならば、以下のコマンドを実行してください。なお、作業は「/var/spool/wwwoffle
」を読み取れる権限があるユーザで行ってください。
estwolefind /var/spool/wwwoffle | estcmd gather -cl -fm -il ja -bc -px @uri -px _lfile -sd -cm casket -
あとは、普通にestseek.cgi
で検索を行うことができます。定期的に上記のコマンドを実行するようにすれば、快適なWebライフの一助となるでしょう。
COPYING
」ファイルを読んでください。make mac
」、HP-UXの場合は「make hpux
」を実行したか確認してください。ビルドに必要なコマンド(ar
やld
など)がパスに含まれているかどうか確認してください。それでもダメなら、メーリングリストか作者に報告してください。