User's Guide of Hyper Estraier Version 1 (Japanese)
Author: Mikio Hirabayashi
Description: User's Guide of Hyper Estraier
Keywords: Hyper Estraier, Estraier, full-text search, API

# ユーザガイド

Copyright (C) 2004-2007 Mikio Hirabayashi
Last Update: Tue, 06 Mar 2007 12:05:18 +0900
[English/Japanese] [HOME]

## 目次

1. はじめに
2. 文書の属性
3. ファイル形式
4. 検索条件式
5. 検索語の抽出
6. 管理用コマンド
7. 検索用CGIスクリプト
8. 表示用CGIスクリプト
9. インデックスの構造
10. 助言
11. よく聞かれる質問

## はじめに

このガイドでは、Hyper Estraierのアプリケーションの詳細な使い方を説明します。イントロダクションをまだお読みでない場合は、先にそちらに目を通しておいてください。

Hyper Estraierは、いわゆるインデックス型の検索システムです。検索を行う前に、対象文書の情報を登録したインデックスを準備しておく必要があります。その手間がかかるかわりに、とても高速に検索を行うことができます。Hyper Estraierはインデックスを管理するコマンド「`estcmd`」とインデックスを使って検索を行うCGIスクリプト「`estseek.cgi`」からなります。つまり、コマンドラインでインデックスの管理作業を行い、Webブラウザで検索を行うことになります。

`estcmd`は様々な形式の文書を扱うことができ、またインデックスに対する多様な管理操作を行うことができます。このガイドでは、文書の扱われ方やインデックスの管理方法について詳細に説明します。

Hyper Estraierは様々な検索方法をサポートします。複数の検索語を組み合わせたり、文書の属性を使って検索したりすることができます。また、`estseek.cgi`の設定により、表示方法をカスタマイズすることができます。このガイドではそれらの方法についても説明します。

## 文書の属性

Hyper Estraierが扱う文書には、本文の情報だけでなく、タイトルなどの属性情報をつけることができます。属性は様々な応用ができます。属性を使った検索もできますし、更新日時の属性は差分更新の判断にも使われます。

### 属性名

属性には名前がつけられます。属性名は自由につけることができるのですが、Hyper Estraierが標準的に使う属性はシステム属性として予め定義されています。システム属性の名前には「`@`」が先頭につきます。システム属性は以下のものがあります。

- `@id` : 文書をインデックスに登録した際に自動的に振られます。
- `@uri` : 文書の参照方法を示します。全ての文書に必須です。
- `@digest` : 文書のメッセージダイジェストを示します。登録時に自動算出されます。
- `@cdate` : 文書の作成日時を示します。
- `@mdate` : 文書の最終更新日時を示します。差分更新に使われます。
- `@adate` : 文書の最終参照日時を示します。
- `@title` : 文書のタイトルです。検索結果で見出しとして扱われます。
- `@author` : 文書の著者です。
- `@type` : 文書のメディアタイプです。
- `@lang` : 文書の言語です。
- `@genre` : 文書の様式です。
- `@size` : 文書のサイズです。
- `@weight` : 文書のスコアリングの重み付けです。
- `@misc` : 文書の雑多な情報です。

システム属性以外の属性はユーザ定義属性と呼ばれます。後述の文書ドラフト形式を使うと、任意のシステム属性とユーザ定義属性をつけることができます。HTMLのmeta要素やMIMEのヘッダもユーザ属性として扱われます。属性名は「`%`」で始まってはいけません。

### 属性の型

属性には2種類の型があります。文字列型と数値型です。文字列型は、任意の文字列です。文字列型の値には、完全一致、前方一致、後方一致、部分一致の判定ができます。数値型は、数値または日付の情報を表したものです。数値型は文字列を数値に直した上で、大小の判定が行われます。数値型の値は形式によって扱われ方が違います。日付として解釈される場合、UNIX紀元（1970年1月1日0時0分0秒）からの経過秒数が判定に使われます。

- 全てが数字 → 10進数として解釈される。
- 先頭が0x → 16進数として解釈される。
- W3CDTF（例：1978-02-11T18:05:32+09:00） → 日付として解釈される。
- RFC822（例：Sat, 11 Feb 1978 18:05:32 +0900） → 日付として解釈される。
- YYYY/MM/DD形式（1978/02/11 18:05:32） → 日付として解釈される。
- 上記以外 → -1として解釈される。

属性がどの型であるかは登録時には決定されません。検索時に属性をどちらの型として解釈するか指定されます。属性の長さに制限はありません。

文書の属性や本文に指定する文字列はUTF-8で表現されている必要があります。テキストファイルやHTMLなどでそれ以外の文字コードを使っている場合は、UTF-8に変換してください。なお、`estcmd`は文字コードを自動判定して変換処理を行います。

システム属性でもユーザ属性でも、実際にどのような値を入れるかはユーザやアプリケーションに任されます。指定する側と解釈する側で合意が取れていれば問題ないわけですが、RFCなどで関連する規定がある場合はそれに従うのがよいでしょう。例えば、「`@type`」にはRFC2045のメディアタイプの書式を用い、「`@lang`」にはISO639の言語コード（「ja」「en」など）を用いるとよいでしょう。ユーザ定義属性の仕様を決める際にはDublin Coreの規格を参考にするといいかもしれません。

### URI属性

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以外のアルゴリズムを使っても構いませんし、本文以外のデータ（ファイルそのものなど）を対象としてダイジェストを計算しても構いません。本文に更新があったならばダイジェストも変化するということが唯一の要件です。

### 重み付け属性

特定の文書を検索結果の上位に表示されやすいようにするには、重み付け属性を使うと便利です。例えば元のスコアが100で重み付けが1.5の場合、重み付けされたスコアは150になります。デフォルトでは、重み付けはP2PのノードAPI（ノードサーバ）を利用した場合にのみ行われ、インデクシングの際にではなく、検索の際に行われます。したがって、ノードサーバにおいては、文書の属性を編集することによって動的に重み付けを変更できます。`estcmd`やコアAPIでオプションを指定すれば、インデクシング時に静的に重み付けを行うこともできます。

## ファイル形式

`estcmd`が扱う4種類のファイル形式のそれぞれがどのように扱われるかを説明します。その他の形式を扱うためのフィルタについては後述します。

### プレーンテキスト

特に構造のない文字列です。デフォルトでは、ファイル名の接尾辞が「`.txt`」「`.text`」「`.asc`」の場合にプレーンテキストとして扱われます。

- 文字コードは自動判定されます。
- @type属性として「text/plain」が記録されます。
- @size属性としてファイルサイズが記録されます。

### HTML

言わずもがな、Webで使われるハイパーテキストです。デフォルトでは、ファイル名の接尾辞が「`.html`」「`.htm`」「`.xhtml`」「`.xht`」の場合にHTMLとして扱われます。

- 文字コードは自動判定されますが、meta要素で文字コードが指定された場合はそちらが優先されます。
- title要素があれば、その内容が@title属性として記録されます。
- meta要素のname属性でauthorが指定されていれば、そのcontent要素の値が@author属性として記録されます。
- html要素にlang属性もしくはxml:lang属性があれば、その値が@lang属性として記録されます。
- @type属性として「text/html」が記録されます。
- @size属性としてファイルサイズが記録されます。
- meta要素のname属性またはhttp-equiv属性が指定されていれば、その属性値を小文字に変換した名前のユーザ属性として、content要素の値を記録します。
- @title属性の値は隠しテキストとして扱われます。

隠しテキストについては後述します。

### MIME（電子メール）

RFC822に基づくメッセージ交換のためのデータ形式です。デフォルトでは、ファイル名の接尾辞が「`.eml`」「`.mime`」「`.mht`」「`.mhtml`」の場合にMIMEとして扱われます。

- 文字コードは自動判定されますが、Content-Typeヘッダで文字コードが指定された場合はそちらが優先されます。
- Subjectヘッダがあれば、その内容が@title属性として記録されます。
- Fromヘッダがあれば、その内容が@author属性として記録されます。
- Dateヘッダがあれば、その内容が@cdate属性および@mdate属性として記録されます。
- @type属性として「message/rfc822」が記録されます。
- @size属性としてファイルサイズが記録されます。
- 全てのヘッダの値は、ヘッダ名を小文字に変換した名前のユーザ属性として指定されます。
- @title属性の値は隠しテキストとして扱われます。

マルチパートの各パートの中身が「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

    君の行く道は 果てしなく遠い
    だのになぜ 歯をくいしばり
    君は行くのか そんなにしてまで
            若者たち
            佐藤勝,藤田敏雄

文書ドラフトは以下の仕様を満たす必要があります。

- 正常なUTF-8エンコードのテキストから構成されます。
- 改行形式はUNIX形式（LF）かMS-DOS形式（CR+LF）のどちらかです。
- 属性部とテキスト部からなり、両者は最初に出現した空行で区切られます。
- 属性部において、各行は属性の指定として扱われます。属性名と値は最初に出現した「`=`」で区切られます。
- テキスト部において、各行は本文の文字列として扱われます。行頭がタブ文字で始まっている場合、その行は隠しテキストとして扱われます。

属性部において、「`%`」で始まる行は制御命令とみなされて無視されます。文書ドラフトに別の目的のデータを混入させたい場合はこの機能を利用してください。ただし、「`%VECTOR`」とそれに続くタブで始まる行がある場合、それは文書のキーワードベクトルを示します。キーワードベクトルの形式はTSVです。各フィールドには、キーワードとそのスコアが交互に表れます。「`%SCORE`」とそれに続くタブで始まる行がある場合、それは文書の代替スコアを示します。

隠しテキストは、通常の本文と同様に検索語が抽出されますが、検索結果のスニペットでは表示されないことが特徴です。タイトルや著者に含まれる語も全文検索の対象にしたい場合には、タイトルや著者と同じ文字列を隠しテキストとしても指定するとよいでしょう。

文書ドラフトの最大の特徴は、URI属性を指定できることです。つまり、文書ドラフト自体のURIではなく、別のファイルのURIをインデックスに記録することができるのです。WebからHTMLデータを収集して文書ドラフト形式で保存するプログラムを作れば、簡易的なWeb検索エンジンを簡単に実現することができます（付録の`estwaver`コマンドを使えばもっと簡単ですが）。文書ドラフトを保存するオーバーヘッドをかけたくない場合は、いよいよAPIを使うことになります。

文書ドラフトをWeb経由で配送する際には、MIMEタイプを「`text/x-estraier-draft`」にすることを推奨します。ユーザエージェントが文書ドラフトを適切に検出すれば、そのままインデックスに登録したり、適切なビューワで表示したりできるようになります。

## 検索条件式

検索条件には、全文検索条件と属性検索条件の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]`」を置き、正規表現の場合は文字列の前に空白を挟んで「`[RX]`」を置きます。例えば、「`[BW] euro`」だと「`euro`」で始まる単語を含む文書を検索します。「`[EW] sphere`」だと「`sphere`」で終わる単語を含む文書を検索します。「`[RX] ^inter.*al$`」だと「`inter`」で始まって「`al`」で終わる単語を含む文書を検索します。

### 全文検索条件の簡便書式

Googleなどの検索エンジンでは、空白で区切ることでAND条件を指定できます。そのような挙動の方が望ましい場合は、簡便書式を使うことができます。簡便書式を使うかどうかは、アプリケーションのコマンドラインのオプションや設定ファイルで指定します。`estseek.cgi`のデフォルトの設定では、簡便書式が使われるようになっています。

簡便書式では、空白または「`&`」で区切るとAND条件になります。例えば、「`インターネット セキュリティ`」と入力すると、「`インターネット`」と「`セキュリティ`」の両方を含む文書を検索します。

複数の検索語を「`""`」で括ると、フレーズ検索ができます。例えば、「`"United Nations"`」と入力すると、「`United`」の直後に「`Nations`」が出現する文書を検索します。

「`!`」を使うとNOT検索ができます。例えば、「`スキー ! スノボー`」と入力すると、「`スキー`」を含むが「`スノボー`」を含まない文書を検索します。

「`|`」を使うとOR検索ができます。例えば、「`レモン | ライム`」と入力すると、「`レモン`」か「`ライム`」の片方または両方を含む文書を検索します。

「`|`」の優先順位が「`&`」や「`!`」より高いのは通常書式と同じです。

簡便書式においては、ワイルドカードによって前方一致や後方一致や正規表現の条件を指定することができます（日本語には効果がありません）。前方一致の場合は文字列の後に「`*`」を置き、後方一致の場合は文字列の前に「`*`」を置き、正規表現の場合は文字列の前後に「`*`」を置きます。例えば、「`euro*`」だと「`euro`」で始まる単語を含む文書を検索します。「`*sphere`」だと「`sphere`」で終わる単語を含む文書を検索します。「`*^inter.*al$*`」だと「`inter`」で始まって「`al`」で終わる単語を含む文書を検索します。

空白や「&」「!」「|」「*」を検索語そのものとして指定したい場合は、フレーズ検索を応用してください。例えば「AT&T」を検索したい場合は、「"AT&T"」とします。

### 全文検索条件のその他の書式

粗略書式は、簡便書式よりもさらに単純な書式です。空白で区切るとAND条件になり、「`|`」で区切るとOR条件になり、「`""`」で挟むとフレーズ検索になるところは簡便書式と同じです。ただし、「`&`」は通常の文字として扱われます。また、OR条件を指定するには、検索語の前に「`-`」をつけて、「`unix -linux`」などとして表現します。粗略書式では、ワイルドカードなどの特殊機能は全て無効になります。

論理和書式は、空白で区切った各トークンのOR条件を指定するものです。論理積書式は、空白で区切った各トークンのAND条件を指定するものです。論理和書式や論理積書式においても、ワイルドカードなどの特殊機能は全て無効になります。

### 属性検索条件

属性検索条件式は、各文書が持つ属性に対して演算子を適用して、該当する文書を検索するためのものです。属性条件式は属性名と演算子と値を空白で区切って並べたものです。例えば、「`@title STRINC 重要`」と指定すると、タイトルに「`重要`」という文字列を含む文書だけに絞り込みます。「`STRINC`」は演算子です。属性検索用の演算子には以下のものがあります。

- `STREQ` : 指定した文字列と一致する。
- `STRNE` : 指定した文字列と一致しない。
- `STRINC` : 指定した文字列を含む。
- `STRBW` : 指定した文字列で始まる。
- `STREW` : 指定した文字列で終わる。
- `STRAND` : 指定した文字列の全てのトークンを含む。
- `STROR` : 指定した文字列の一つ以上のトークンを含む。
- `STROREQ` : 指定した文字列の一つ以上のトークンと一致する。
- `STRRX` : 指定した文字列の正規表現に合致する。
- `NUMEQ` : 数値や日付が指定したものと等しい。
- `NUMNE` : 数値や日付が指定したものと等しくない。
- `NUMGT` : 数値や日付が指定したものより大きい。
- `NUMGE` : 数値や日付が指定したものと同じかより大きい。
- `NUMLT` : 数値や日付が指定したものより小さい。
- `NUMLE` : 数値や日付が指定したものと同じかより小さい。
- `NUMBT` : 数値や日付が指定したものの間である。

演算子の前に「`!`」を置いて「`!STREQ`」などとすると、条件に当てはまらないものに絞り込みます。例えば、「`@title !STRBW ※未承諾広告`」などとします。文字列の演算子の前に「`I`」を置いて「`ISTREQ`」などとすると、文字列の大文字と小文字の違いを無視します。「`!`」と「`I`」を両方指定する場合、「`!ISTREQ`」などとします。演算子を省略して属性名のみを指定した場合、値は問わずに、その属性を備える文書を該当とみなします。`STRAND`と`STROR`と`STROREQ`と`NUMBT`は空白で区切った複数の文字列を引数に取ります。「`NUMBT 51 100`」は、「51から100まで」という意味であり、境界値も範囲に含みます。

属性名を「`,`」で区切って並べると、並べた属性のいずれかという意味になります。例えば「`from,to,cc STRINC mikio`」は、「fromかtoかccのどれかにmikioを含む」という意味になります。「`,`」の前後に空白を入れてはいけません。

属性条件は複数指定することができます。その場合、指定された全ての条件を満たす文書が該当とみなされます。なお、属性検索を行うと候補の全ての文書の情報を参照するため、検索速度が多少遅くなります。後述の属性インデックスを使うと属性検索を高速化することができます。

### 順序指定

順序指定式によって、結果の表示順序を指定することもできます。順序指定式は属性名と演算子を空白で区切って並べたものです。例えば、「`@size NUMA`」と指定すると、サイズが小さい文書から並べられます。「`NUMA`」は演算子です。順序指定用の演算子には以下のものがあります。演算子を省略した場合は、「`STRA`」が指定されたとみなします。

- `STRA` : 文字列（辞書順）の昇順。
- `STRD` : 文字列（辞書順）の降順。
- `NUMA` : 数値または日付の昇順。
- `NUMD` : 数値または日付の降順。

順序指定を行わなかった場合は、スコアの降順になります。スコアとは、各文書に指定した検索語がどのくらい含まれるかという指標です。AND検索やOR検索で複数の語が指定された場合、TF-IDF法に基づいてスコアの調整が行われます。「`the`」や「`する`」といった頻出語よりも、「`hippopotamus`」や「`咀嚼`」といった特徴的な語句に高いスコアをつけるということです。また、検索語が同数程度含まれるならば、総語数の多い文書よりも総語数の少ない文書の方がスコアが高くなります。スコアの昇順に並べたい場合は、属性名を省いて単に「`[SCA]`」と指定してください。

順序指定式は一つしか指定できません。なお、順序指定を行うと候補の全ての文書の情報を参照するため、検索速度が多少遅くなります。

### 類似検索

ある文書に似た文書を探す、類似検索式もサポートされます。関連文書検索とも呼ばれることもあります。類似検索の利用方法はアプリケーションによって様々ですが、典型的には、検索結果に示される文書のひとつをユーザが指定して、それに似た文書を再検索するために使われます。`estseek.cgi`の場合、「`[similar]`」というリンクを選択すると類似検索を行うことができます。類似検索の結果は類似度の降順に並べられます。類似度はベクトル空間モデルという考え方に基づいて算出されます。文書からキーワードを取り出してベクトルとして表現し、ベクトル同士のなす角の余弦を類似度とするものです。ちょっと難しい言い方になりましたが、要するに、語彙が似通った文書は類似度が高くなるということです。キーワードとしては、文書内の頻度にTF-IDF法で重みづけを行った結果が上位の語句が選択されます。

類似検索式をユーザが入力する必要はありませんが、アプリケーションに類似検索機能をつけるためには書式を知っておく必要があります。検索フレーズが「`[SIMILAR]`」という演算子で始まっている場合に類似検索が行われます。「`[SIMILAR]`」の後ろには、種文書（類似判定の元となる文書）のベクトルの要素を列挙します。各要素は「`WITH`」演算子で始まり、スコアの数値とキーワードの文字列を空白で区切って指定します。例えば、`300`の「`日本`」と`250`の「`japan`」と`100`の「`東京`」を含む文書を仮想の種文書とする場合は、「`[SIMILAR] WITH 300 日本 WITH 250 japan WITH 100 東京`」と指定します。

「`[SIMILAR] 24 2048 8192 WITH 300 日本 WITH 250 japan`」のように、演算子の後に空白で区切って3つの数値を指定することができます。この例の場合、キーワードの上位24語の各々に該当する文書を2048件ずつ取り出し、その和集合からスコアが上位の8192件の文書を類似度判定の候補として選ぶということを意味します。デフォルトでは上位16語から各々1024件を取り出して上位4096件を候補とします。

関連文書検索と順序指定式を同時に指定した場合、類似度が0.5以上の文書に絞り込んだ上で、順序指定式に基づいて並べられます。なお、関連文書検索の検索速度はとても遅いです。後述のキーワードデータベースを使うと類似検索を高速化することができます。

### 類似隠蔽

検索結果に似たような文書ばかりが並んで鬱陶しい場合は、類似隠蔽機能を利用してください。類似隠蔽機能のインターフェイスはアプリケーションによって異なりますが、0.0から1.0までの類似度を指定します。すると、検索結果の各々の文書に対して、指定した値を越える類似度を持つ他の文書を重ねる処理を行います。重なった文書群の中で表示されるのは最も順位の高いものだけです。類似度の指定は0.7から0.9までの間にすると使いやすいでしょう。

類似度に「`file`」を指定した場合、同じファイルに対する異なるURL（CGI等のクエリ文字列など）の文書を隠蔽します。「`dir`」を指定した場合、同じディレクトリ内にある文書を隠蔽します。「`serv`」を指定した場合、同じサーバ内にある文書を隠蔽します。

### ID検索とURI検索

検索フレーズが「`[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の使い勝手を比べてみてください。

Hyper Estraierには、N-gram方式と分かち書き方式を併用するオプションもあります。N-gramで抽出した語からなるメインインデックスとは別に、分かち書きで抽出した重要語だけからなる補助インデックスを管理します。そうすると、検索語が適切に分かち書きできた場合は、補助インデックスを見て、高速で高精度な検索を行うことができます。分かち書きがうまく行えなかった場合も、メインインデックスを見れば、検索漏れのない結果を提示することができます。

## 管理用コマンド

ここでは、インデックス管理用コマンド`estcmd`の詳細な仕様を説明します。検索もできるので、`estcmd`をスクリプト言語から呼び出せばそれなりのアプリケーションが簡単に作れます。

### 書式

estcmdは多くのサブコマンドの集合体です。サブコマンドの名前は第1引数で指定されます。その他の引数はサブコマンドの種類に応じて解釈されます。dbという引数はインデックスのパスです。

`estcmd create [-tr] [-apn|-acc] [-xs|-xl|-xh|-xh2|-xh3] [-sv|-si|-sa] [-attr name type] db`
  インデックスを作成します。
  -trをつけると、既にインデックスがある場合にも新しいインデックスを作成します。
  -apnをつけると、全ての言語をN-gram法で処理します。
  -accをつけると、N-gram法の代わりに文字種分類法を利用します。
  -xsをつけると、50000件未満の文書を登録することを想定してインデックスを作成します。
  -xlをつけると、300000件以上の文書を登録することを想定してインデックスを作成します。
  -xhをつけると、1000000件以上の文書を登録することを想定してインデックスを作成します。
  -xh2をつけると、5000000件以上の文書を登録することを想定してインデックスを作成します。
  -xh3をつけると、10000000件以上の文書を登録することを想定してインデックスを作成します。
  -svをつけると、スコア情報を破棄します。
  -siをつけると、スコア情報を32ビットの数値として記録します。
  -saをつけると、スコア情報をそのまま保存した上で検索時に調整されないようにマークします。
  -attrは属性インデックスの対象となる属性名とデータ型を指定します。複数指定可能です。

`estcmd put [-tr] [-cl] [-ws] [-apn|-acc] [-xs|-xl|-xh|-xh2|-xh3] [-sv|-si|-sa] db [file]`
  文書ドラフト形式のファイルを登録します。
  fileは対象のファイルを指定しますが、省略した場合は標準入力が読み込まれます。
  -trをつけると、既にインデックスがある場合にも新しいインデックスを作成します。
  -clを付けると、上書きされた文書の領域を整理します。
  -wsを付けると、重み付け属性を静的に適用します。
  -apnをつけると、全ての言語をN-gram法で処理します。
  -accをつけると、N-gram法の代わりに文字種分類法を利用します。
  -xsをつけると、50000件未満の文書を登録することを想定してインデックスを作成します。
  -xlをつけると、300000件以上の文書を登録することを想定してインデックスを作成します。
  -xhをつけると、1000000件以上の文書を登録することを想定してインデックスを作成します。
  -xh2をつけると、5000000件以上の文書を登録することを想定してインデックスを作成します。
  -xh3をつけると、10000000件以上の文書を登録することを想定してインデックスを作成します。
  -svをつけると、スコア情報を破棄します。
  -siをつけると、スコア情報を32ビットの数値として記録します。
  -saをつけると、スコア情報をそのまま保存した上で検索時に調整されないようにマークします。

`estcmd out [-cl] [-pc enc] db expr`
  特定の文書の情報をインデックスから削除します。
  exprは対象のID番号かURIかローカルパスを指定します。
  -clを付けると、削除された文書の領域を整理します。
  -pcはファイルのパスの文字コードを指定します。デフォルトはISO-8859-1です。

`estcmd edit [-pc enc] db expr name [value]`
  特定の文書の属性を更新します。
  exprは対象のID番号かURIかローカルパスを指定します。
  nameは属性の名前を指定します。
  valueは属性の値を指定します。省略した場合その属性は削除されます。
  -pcはファイルのパスと属性値の文字コードを指定します。デフォルトはISO-8859-1です。

`estcmd get [-nl|-nb] [-pidx path] [-pc enc] db expr [attr]`
  特定の文書の情報を文書ドラフト形式で出力します。
  exprは対象のID番号かURIかローカルパスを指定します。
  attrを付けると、その属性の値のみを出力します。
  -nlを付けると、ファイルロックをかけないでインデックスを開きます。
  -nbを付けると、ブロックせずにファイルロックをかけます。
  -pidxは検索対象に追加する疑似インデックスのパスを指定します。複数指定可能です。
  -pcはファイルのパスの文字コードを指定します。デフォルトはISO-8859-1です。

`estcmd list [-nl|-nb] [-lp] db`
  インデックスに登録されている全ての文書のID番号を出力します。
  -nlを付けると、ファイルロックをかけないでインデックスを開きます。
  -nbを付けると、ブロックせずにファイルロックをかけます。
  -lpを付けると、「file://」のURIに対応するローカルパスも出力します。

`estcmd uriid [-pidx path] [-nl|-nb] [-pc enc] db expr`
  指定したURIの文書のID番号を出力します。
  exprは対象のURIかローカルパスを指定します。
  -nlを付けると、ファイルロックをかけないでインデックスを開きます。
  -nbを付けると、ブロックせずにファイルロックをかけます。
  -pidxは検索対象に追加する疑似インデックスのパスを指定します。複数指定可能です。
  -pcはファイルのパスの文字コードを指定します。デフォルトはISO-8859-1です。

`estcmd meta db [name [value]]`
  インデックスのメタデータを扱います。
  nameはメタデータの名前を指定します。省略した場合は名前の一覧を出力します。
  valueは記録するメタデータの値を指定します。省略した場合は現状の値を出力します。空文字列の場合は削除します。

`estcmd inform [-nl|-nb] db`
  インデックスに登録された文書数や異なり語数などの情報を出力します。
  -nlを付けると、ファイルロックをかけないでインデックスを開きます。
  -nbを付けると、ブロックせずにファイルロックをかけます。

`estcmd optimize [-onp] [-ond] db`
  インデックスを最適化して、不要な領域を削除します。
  -onpを付けると、削除された文書の領域を回収する処理を省略します。
  -ondを付けると、データベースファイルの最適化を省略します。

`estcmd merge [-cl] db target`
  別のインデックスをマージします。
  targetは別のインデックスのパスを指定します。
  -clを付けると、削除された文書の領域を整理します。

`estcmd repair [-rst|-rsh] db`
  壊れたインデックスを修復します。
  -rstを付けると、厳密な整合性検査を行います。
  -rshを付けると、整合性検査を省略します。

`estcmd search [-nl|-nb] [-pidx path] [-ic enc] [-vu|-va|-vf|-vs|-vh|-vx|-dd] [-sn wnum hnum anum] [-kn num] [-ec rn] [-gs|-gf|-ga] [-cd] [-ni] [-sf|-sfr|-sfu|-sfi] [-hs] [-attr expr] [-ord expr] [-max num] [-sk num] [-aux num] [-dis name] [-sim id] db [phrase]`
  インデックスに登録された文書を検索します。
  phraseは全文検索の検索式を指定します。
  -nlを付けると、ファイルロックをかけないでインデックスを開きます。
  -nbを付けると、ブロックせずにファイルロックをかけます。
  -pidxは検索対象に追加する疑似インデックスのパスを指定します。複数指定可能です。
  -icは引数の文字コードを指定します。デフォルトはUTF-8です。
  -vuを付けると、ID番号とURIをタブ区切りにした形式で結果を出力します。
  -vaを付けると、属性情報を含めたマルチパート形式で結果を出力します。
  -vfを付けると、文書ドラフト形式を含めたマルチパート形式で結果を出力します。
  -vsを付けると、属性情報とスニペットを含めたマルチパート形式で結果を出力します。
  -vhを付けると、属性情報とスニペットを人間が読みやすい形式にして結果を出力します。
  -vxを付けると、属性情報とスニペットをXML形式にして結果を出力します。
  -ddを付けると、結果を文書ドラフト形式のファイルとして保存します。
  -snは、スニペットの全体の幅と冒頭から抽出する幅とハイライトされる語の周辺から抽出する幅を指定します。
  -knは、抽出するキーワードの数を指定します。デフォルトではキーワード抽出は行いません。
  -umを付けると、キーワードを抽出する際に形態素解析器を用います。
  -ecは類似隠蔽の下限類似度を0.0から1.0までの実数で指定します。「serv」を指定するとサーバ単位になり、「dir」を指定するとディレクトリ単位になり、「file」を指定するとファイル単位になります。
  -gsを付けると、N-gramの全てのキーの存在を検査します。デフォルトは1個置きです。
  -gfを付けると、N-gramのキーを2個置きで検査します。
  -gaを付けると、N-gramのキーを3個置きで検査します。
  -cdを付けると、文書の内容がフレーズと確実に適合するか検査します。
  -niを付けると、TF-IDF法によるスコアの調整を行いません。
  -sfを付けると、検索式を簡便書式として扱います。
  -sfrを付けると、検索式を粗略書式として扱います。
  -sfuを付けると、検索式を論理和書式として扱います。
  -sfiを付けると、検索式を論理積書式として扱います。
  -hsを付けると、該当文書のスコア情報を属性として出力します。
  -attrは絞り込みの属性条件を指定します。複数指定可能です。
  -ordはソート条件を指定します。デフォルトはスコアの降順です。
  -maxは最大表示件数を指定します。負数にすると無制限になります。デフォルトは10件です。
  -skは表示をスキップする件数を指定します。デフォルトは0件です。
  -auxは補助インデックスの結果を採用する許可を指定します。0を越えない値を指定すると補助インデックスは使われません。デフォルトは32件です。
  -disは重複回避属性の名前を指定します。
  -simは類似検索の種文書のID番号を指定します。

`estcmd gather [-tr] [-cl] [-ws] [-no] [-fe|-ft|-fh|-fm] [-fx sufs cmd] [-fz] [-fo] [-rm sufs] [-ic enc] [-il lang] [-bc] [-lt num] [-lf num] [-pc enc] [-px name] [-aa name value] [-apn|-acc] [-xs|-xl|-xh|-xh2|-xh3] [-sv|-si|-sa] [-ss name] [-sd] [-cm] [-cs num] [-ncm] [-kn num] [-um] db [file|dir]`
  ファイルシステムを探索して文書を登録します。
  第3引数としてファイル名を指定すると、そのファイルから処理対象のパスのリストを読み込みます。「-」を指定した場合、標準入力が読み込まれます。findコマンドの出力を読み込むと便利です。
  第3引数としてディレクトリ名を指定すると、そのディレクトリ以下の全てのファイルを処理対象にします。
  -trをつけると、既にインデックスがある場合にも新しいインデックスを作成します。
  -clを付けると、上書きされた文書の領域を整理します。
  -wsを付けると、重み付け属性を静的に適用します。
  -noを付けると、処理内容の表示だけを行い、実際の処理を行いません。
  -feを付けると、処理対象の全てのファイルを文書ドラフトとして扱います。デフォルトでは、拡張子によって文書形式を判断し、サポート外のものは無視されます。
  -ftを付けると、処理対象の全てのファイルをプレーンテキストとして扱います。
  -fhを付けると、処理対象の全てのファイルをHTMLとして扱います。
  -fmを付けると、処理対象の全てのファイルをMIMEとして扱います。
  -fxは、ファイル名の接尾辞に関連づけた外部コマンドを指定します。カンマ区切りで複数の接尾辞を指定できます。「*」だと全てのファイルに一致します。コマンド名の前に「T@」をつけるとその出力がプレーンテキストとして解析され、「H@」をつけるとHTMLとして解析され、「M@」をつけるとMIMEとして解析され、いずれでもない場合は文書ドラフトとして解析されます。このオプションは複数回指定できます。
  -fzを付けると、-fxの条件に当てはまらないファイルを無視します。
  -foを付けると、処理対象のファイルを読み込みません。外部フィルタの効率化のために使います。
  -rmは、処理後に削除するファイルを指定します。カンマ区切りで複数の接尾辞を指定できます。「*」を指定すると全てのファイルを削除します。このオプションは複数回指定できます。
  -icは対象文書の文字コードを指定します。デフォルトは自動判定です。
  -ilは文字コードの判定で優先される言語を指定します。デフォルトは英語です。
  -bcを付けると、バイナリファイルを検出して処理対象から除外します。
  -ltは、解析するテキストのサイズ制限をキロバイト単位で指定します。デフォルトは128KBです。負数にすると無制限になります。制限を超えた場合、先頭から制限サイズまでのテキストが解析されます。
  -lfは、読み込むファイルのサイズ制限をメガバイト単位で指定します。デフォルトは32MBです。負数にすると無制限になります。制限を超えた場合、そのファイルは無視されます。
  -pcはファイルのパスの文字コードを指定します。デフォルトはISO-8859-1です。
  -pxはパスのリストから読み取る属性の名前を指定します。パスのリストはTSV形式にすることができ、第1フィールドは対象文書のパス名、第2フィールド以降は属性値の定義として扱われます。-pxによって第2フィールド以降に対応する属性名を定義します。このオプションは複数回指定できます。
  -aaは追加する属性の名前と値を指定します。このオプションは複数回指定できます。
  -apnをつけると、全ての言語をN-gram法で処理します。
  -accをつけると、N-gram法の代わりに文字種分類法を利用します。
  -xsをつけると、50000件未満の文書を登録することを想定してインデックスを作成します。
  -xlをつけると、300000件以上の文書を登録することを想定してインデックスを作成します。
  -xhをつけると、1000000件以上の文書を登録することを想定してインデックスを作成します。
  -xh2をつけると、5000000件以上の文書を登録することを想定してインデックスを作成します。
  -xh3をつけると、10000000件以上の文書を登録することを想定してインデックスを作成します。
  -svをつけると、スコア情報を破棄します。
  -siをつけると、スコア情報を32ビットの数値として記録します。
  -saをつけると、スコア情報をそのまま保存した上で検索時に調整されないようにマークします。
  -ssは、代替スコアとして扱う属性の名前を指定します。
  -sdを付けると、ファイルの更新日時を文書の属性として追加します。
  -cmを付けると、文書の属性の更新日時がファイルの更新日時より古い場合にのみ登録を行います。
  -csは、キャッシュメモリのサイズをメガバイト単位で指定します。デフォルトは64MBです。
  -ncmをつけると、仮想メモリの残量検査を省略します。
  -knは、抽出するキーワードの数を指定します。デフォルトではキーワード抽出は行いません。
  -umを付けると、キーワードを抽出する際に形態素解析器を用います。

`estcmd purge [-cl] [-no] [-fc] [-pc enc] [-attr expr] db [prefix]`
  インデックス内にあってファイルシステム上にない文書の情報を削除します。
  prefixを指定すると、その文字列で始まるURIの文書のみを対象とします。ディレクトリのローカルパスでも指定できます。
  -clを付けると、削除された文書の領域を整理します。
  -noを付けると、処理内容の表示だけを行い、実際の処理を行いません。
  -fcを付けると、ファイルがあるかないかにかかわらず文書情報を削除します。
  -pcはファイルのパスの文字コードを指定します。デフォルトはISO-8859-1です。
  -attrは絞り込みの属性条件を指定します。複数指定可能です。

`estcmd extkeys [-no] [-fc] [-dfdb file] [-ncm] [-ni] [-kn num] [-um] [-attr expr] db [prefix]`
  インデックス内の各文書のキーワードを抽出したデータベースを作成します。
  prefixを指定すると、その文字列で始まるURIの文書のみを対象とします。
  -noを付けると、処理内容の表示だけを行い、実際の処理を行いません。
  -fcを付けると、既にキーワードが登録されている文書でもキーワードを作りなおします。
  -dfdbは、文書頻度を記録した外部データベースを指定します。デフォルトではインデックスから動的に文書頻度を計算します。
  -ncmをつけると、仮想メモリの残量検査を省略します。
  -niを付けると、TF-IDF法によるスコアの調整を行いません。
  -knは、抽出するキーワードの数を指定します。デフォルトは32個です。
  -umを付けると、キーワードを抽出する際に形態素解析器を用います。
  -attrは絞り込みの属性条件を指定します。複数指定可能です。

`estcmd words [-nl|-nb] [-dfdb file] [-kw|-kt] db`
  インデックス内の異なり語とそのレコードサイズ（文書頻度）を出力します。
  -nlを付けると、ファイルロックをかけないでインデックスを開きます。
  -nbを付けると、ブロックせずにファイルロックをかけます。
  -dfdbは、結果を格納する外部のデータベースを指定します。デフォルトでは標準出力にTSV形式で出力されます。外部データベースが既に存在する場合は、各レコードの値を加算します。
  -kwを付けると、キーワードとその該当文書数を出力します。
  -ktを付けると、キーワードとその関連語を出力します。

`estcmd draft [-ft|-fh|-fm] [-ic enc] [-il lang] [-bc] [-lt num] [-kn num] [-um] [file]`
  各種形式のファイルを文書ドラフト形式に変換して出力します。
  fileは対象のファイルを指定しますが、省略した場合は標準入力が読み込まれます。
  -ftを付けると、対象をプレーンテキストとして扱います。デフォルトは文書ドラフト形式です。
  -fhを付けると、対象をHTMLとして扱います。
  -fmを付けると、対象をMIMEとして扱います。
  -icは対象文書の文字コードを指定します。デフォルトは自動判定です。
  -ilは文字コードの判定で優先される言語を指定します。デフォルトは英語です。
  -bcを付けると、バイナリファイルを検出して処理対象から除外します。
  -ltは、解析するテキストのサイズ制限をキロバイト単位で指定します。デフォルトは256KBです。負数にすると無制限になります。制限を超えた場合、先頭から制限サイズまでのテキストが解析されます。
  -knは、抽出するキーワードの数を指定します。
  -umを付けると、キーワードを抽出する際に形態素解析器を用います。

`estcmd break [-ic enc] [-il lang] [-apn|-acc] [-wt] [file]`
  プレーンテキストを検索語に分解します。
  fileは対象のファイルを指定しますが、省略した場合は標準入力が読み込まれます。「@」で始まる場合、「@」より後ろの文字列そのものを処理対象とします。
  -icは処理対象の文字コードを指定します。デフォルトは自動判定です。
  -ilは文字コードの判定で優先される言語を指定します。デフォルトは英語です。
  -apnをつけると、全ての言語をN-gram法で処理します。
  -accをつけると、N-gram法の代わりに文字種分類法を利用します。
  -wtを付けると、「末尾の1-gram」も出力します。

`estcmd iconv [-ic enc] [-il lang] [-oc enc] [file]`
  文字コードを変換します。
  fileは対象のファイルを指定しますが、省略した場合は標準入力が読み込まれます。「@」で始まる場合、「@」より後ろの文字列そのものを処理対象とします。
  -icは処理対象の文字コードを指定します。デフォルトは自動判定です。
  -ilは文字コードの判定で優先される言語を指定します。デフォルトは英語です。
  -ocは出力の文字コードを指定します。デフォルトはUTF-8です。

`estcmd regex [-inv] [-repl str] expr [file]`
  正規表現を含む行を出力します。
  exprは正規表現を指定します。
  fileは対象のファイルを指定しますが、省略した場合は標準入力が読み込まれます。
  -invを付けると、正規表現にマッチしない行を出力します。
  -replを付けると、正規表現にマッチする部分を指定した文字列に置き換えるとともに、マッチしない行も出力します。

`estcmd scandir [-tf|-td] [-pa|-pu] [dir]`
  ディレクトリに含まれるファイルを再帰的に探索して出力します。
  dirは探索の起点となるディレクトリを指定しますが、省略した場合はカレントディレクトリが指定されます。
  -tfを付けると、通常のファイルのみを出力します。
  -tdを付けると、ディレクトリのみを出力します。
  -paを付けると、絶対パスを出力します。
  -puを付けると、URLを出力します。

`estcmd multi [-db db] [-nl|-nb] [-ic enc] [-gs|-gf|-ga] [-cd] [-ni] [-sf|-sfr|-sfu|-sfi] [-hs] [-hu] [-attr expr] [-ord expr] [-max num] [-sk num] [-aux num] [-dis name] [phrase]`
  ローカルメタ検索のテストを行います。
  phraseは全文検索の検索式を指定します。
  -dbは、メタ検索の対象となるデータベースを指定します。複数指定可能です。
  -nlを付けると、ファイルロックをかけないでインデックスを開きます。
  -nbを付けると、ブロックせずにファイルロックをかけます。
  -pidxは検索対象に追加する疑似インデックスのパスを指定します。複数指定可能です。
  -icは引数の文字コードを指定します。デフォルトはUTF-8です。
  -gsを付けると、N-gramの全てのキーの存在を検査します。デフォルトは1個置きです。
  -gfを付けると、N-gramのキーを2個置きで検査します。
  -gaを付けると、N-gramのキーを3個置きで検査します。
  -cdを付けると、文書の内容がフレーズと確実に適合するか検査します。
  -niを付けると、TF-IDF法によるスコアの調整を行いません。
  -sfを付けると、検索式を簡便書式として扱います。
  -sfrを付けると、検索式を粗略書式として扱います。
  -sfuを付けると、検索式を論理和書式として扱います。
  -sfiを付けると、検索式を論理積書式として扱います。
  -hsを付けると、該当文書のスコア情報を出力に含めます。
  -huを付けると、該当文書のうURLを出力に含めます。
  -attrは絞り込みの属性条件を指定します。複数指定可能です。
  -ordはソート条件を指定します。デフォルトはスコアの降順です。
  -maxは最大表示件数を指定します。負数にすると無制限になります。デフォルトは10件です。
  -skは表示をスキップする件数を指定します。デフォルトは0件です。
  -auxは補助インデックスの結果を採用する許可を指定します。0を越えない値を指定すると補助インデックスは使われません。デフォルトは32件です。
  -disは重複回避属性の名前を指定します。

`estcmd randput [-ren|-rla|-reu|-ror|-rjp|-rch] [-cs num] db dnum`
  無作為に生成した文書を登録するテストを行います。
  -renを付けると、英文風の文書のみを登録します。デフォルトは全種類を登録します。
  -rlaを付けると、独文、仏文、西文風の文書のみを登録します。
  -reuを付けると、希文、露文風の文書のみを登録します。
  -rorを付けると、アジア全域の文字を使った文書のみを登録します。
  -rjpを付けると、和文風の文書のみを登録します。
  -rchを付けると、UCS-2の全ての文字を使った文書のみを登録します。
  -csは、キャッシュメモリのサイズをメガバイト単位で指定します。デフォルトは64MBです。

`estcmd wicked db dnum`
  文書の登録、削除、検索、データベースの開閉、最適化などを無作為に繰り返すテストを行います。
  dnumは処理の回数を指定します。

`estcmd regression db`
  回帰テストを行います。

`estcmd version`
  バージョンと著作権の情報を出力します。

全てのサブコマンドは、処理が正常に終了した場合には0を、そうでない場合は1を終了ステータスにします。`put`、`out`、`gather`、`purge`、`randput`、`wicked`、`regression`については、実行中のプロセスに1（SIGHUP）、2（SIGINT）、3（SIGQUIT）、13（SIGPIPE）、15（SIGTERM）のどれかのシグナルを送ることにより、データベースを閉じて正常終了させることができます。

`create`の「`-attr`」オプションにおけるデータ型は、「`seq`」ならシーケンシャル型、「`str`」なら文字列型、「`num`」なら数値型になります。

`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`」オプションも同時につけるとよいでしょう。

`gather`と`extkeys`の実行時には、仮想メモリの空き領域が少ない場合には処理を停止するチェック機能が働きます。UNIX系のOSでスワップ領域を確保していない場合はこのチェックが誤動作する場合がありますので、その際には「`-ncm`」オプションを指定して実行してください。

### 応用例：メールボックスのインデクシング

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`を動作させるには`pdftotext`（xpdfに同梱）をインストールしておくことが必要です。

    PATH=$PATH:/usr/local/share/hyperestraier/filter ; export PATH
    estcmd gather -cl -fx ".pdf" "H@estfxpdftohtml" -fz -ic UTF-8 -sd -cm casket .

`estfxxdwtotxt`はDocuWorksのファイルをプレーンテキスト形式に変換するフィルタです。以下のように利用して、DocuWorksのファイルを対象にしたインデックスを作ることができます。なお、`estfxxdwtotxt`を動作させるにはxdw2textをインストールしておくことが必要です。

    PATH=$PATH:/usr/local/share/hyperestraier/filter ; export PATH
    estcmd gather -cl -fx ".xdw" "T@estfxxdwtotxt" -fz -ic CP932 -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`オプションは検索結果を見やすくするためにつけています。上述の検索語を可変にしたスクリプトを作っておくと便利かもしれません。

### 応用例：XML形式の検索結果

各種のスクリプト言語からHyper Estraierの検索結果を手軽に利用するためには、`estcmd`のXML出力機能を用いるとよいでしょう。XMLの詳しい書式については`estresult.dtd`をご覧ください。

    estcmd search -vx -max 8 casket 'socket AND shutdown'

## 検索用CGIスクリプト

ここでは、検索用CGIスクリプト`estseek.cgi`の詳細な仕様を説明します。設定ファイルの書き方が中心になります。

### 構成

`estseek.cgi`が動作するには、設定ファイルとテンプレートファイルとトップページファイルとヘルプファイルが必要です。それぞれ`estseek.conf`、`estseek.tmpl`、`estseek.top`、`estseek.help`というのが標準的な名前です。

設定ファイルの名前は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
    helpfile: estseek.help
    lockindex: true
    pseudoindex:
    replace: ^file:///home/mikio/public_html/{{!}}http://localhost/
    replace: /index\.html?${{!}}/
    showlreal: false
    deftitle: Hyper Estraier: a full-text search system for communities
    formtype: normal
    perpage: 10 100 10
    attrselect: false
    #genrecheck: private{{!}}private
    #genrecheck: business{{!}}business
    #genrecheck: misc{{!}}miscellaneous
    attrwidth: 80
    showscore: true
    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: 3
    phraseform: 2
    dispproxy:
    candetail: true
    candir: false
    auxmin: 32
    smlrvnum: 32
    smlrtune: 16 1024 4096
    clipview: 2
    clipweight: none
    relkeynum: 0
    spcache:
    wildmax: 256
    qxpndcmd:
    logfile:
    logformat: {time}\t{REMOTE_ADDR}:{REMOTE_PORT}\t{cond}\n

それぞれの変数の機能を以下に示します。

- `indexname` : インデックスのパスを指定します。
- `tmplfile` : テンプレートファイルのパスを指定します。
- `topfile` : トップページファイルのパスを指定します。
- `helpfile` : ヘルプファイルのパスを指定します。
- `lockindex` : インデックスにファイルロックをかけるかどうかを指定します。「`true`」か「`false`」です。
- `pseudoindex` : 検索対象として追加する疑似インデックスのパスを指定します。複数回指定できます。
- `replace` : URIを変換するための正規表現と置換文字列を「`{{!}}`」で区切って指定します。変換文字列内の「`&`」は一致文字列に展開されます。部分式に展開される「`\1`」から「`\9`」も利用できます。複数回指定できます。
- `showlreal` : URIの代わりにローカルの絶対パスを表示するかどうかを指定します。「`true`」か「`false`」です。
- `deftitle` : デフォルトのページタイトルを指定します。
- `formtype` : 入力フォームの種類を指定します。「`normal`」は汎用で、「`web`」はWebサイト用で、「`file`」はファイルシステム用で、「`mail`」はメールボックス用です。
- `perpage` : 表示件数のセレクトボックスの最低値と最大値と増分を指定します。
- `attrselect` : 属性条件の入力にセレクトボックスを使うかを指定します。「`true`」か「`false`」です。
- `genrecheck` : ジャンル属性による絞り込みのためのチェックボックスを指定します。属性値と表示用のラベルを「`{{!}}`」で区切って指定します。複数回指定できます。
- `attrwidth` : 表示する属性値の最大幅を指定します。
- `showscore` : スコアを表示するかを指定します。「`true`」か「`false`」です。
- `extattr` : 表示する属性の名前とラベルを「`|`」で区切って指定します。複数回指定できます。
- `snipwwidth` : 検索結果のスニペットの全体の幅を指定します。
- `sniphwidth` : 検索結果のスニペットを作る際に文書の冒頭から取得する幅を指定します。
- `snipawidth` : 検索結果のスニペットを作る際に検索語の周辺から取得する幅を指定します。
- `condgstep` : N-gramの検査精度を指定します。「`1`」だと全ての語を調べ、「`2`」だと1個置き、「`3`」だと2個置き、「`4`」だと3個置きに調べます。
- `dotfidf` : TF-IDF法を適用するかどうかを指定します。「`true`」か「`false`」です。
- `scancheck` : 文書の内容と検索フレーズの精密検査をする数を指定します。
- `phraseform` : 検索条件式の種類指定します。「`1`」だと通常書式で、「`2`」だと簡便書式で、「`3`」だと粗略書式で、「`4`」だと論理和書式で、「`5`」だと論理積書式です。
- `dispproxy` : 表示用CGIスクリプト（`estproxy.cgi`）のURLを指定します。「`[URI]`」と指定すると各文書のURIに置換されます。省略すると修飾表示は無効になります。
- `candetail` : 詳細表示を有効にするかどうかを指定します。「`true`」か「`false`」です。
- `candir` : ディレクトリ表示を有効にするかどうかを指定します。「`true`」か「`false`」です。
- `auxmin` : 補助インデックスの結果を採用する最低の文書数を指定します。0なら補助インデックスを使いません。
- `smlrvnum` : 類似検索のベクトルの次元数を指定します。0なら類似検索が無効になります。
- `smlrtune` : 類似検索のチューニングパラメータを指定します。キーワード数とキーワード毎の文書数と全体の候補の数を空白区切りで指定します。
- `clipview` : 類似隠蔽の際に表示される文書数を指定します。負数なら類似隠蔽が無効になります。
- `clipweight` : 類似隠蔽の際の重み付けを指定します。「`none`」だと重み付けをせず、「`url`」だとURLを用います。
- `relkeynum` : 表示する関連語の数を指定します。
- `spcache` : スペシャルキャッシュの属性名を指定します。
- `wildmax` : ワイルドカード展開の最大語数を指定します。
- `qxpndcmd` : クエリ展開のコマンドを指定します。空文字列ならクエリ展開が無効になります。
- `logfile` : ログファイルのパスを指定します。
- `logformat` : ログの書式を指定します。「`{time}`」は現在時刻に変換され、「`{cond}`」は検索条件に置換され、「`{hnum}`」は検索の該当件数に置換され、それ以外で「`{}`」で括ったものはその名前の環境変数の値に置換されます。「`\t`」はタブに、「`\n`」は改行に置換されます。

`replace`は正規表現によってURIを変換するのに使います。複数回指定できます。先頭にマッチする「`^`」を駆使すれば接頭辞（ディレクトリ）の変換ができますし、末尾にマッチする「`$`」を駆使すれば接尾辞（拡張子）の変換ができます。例えば、「`\.htm${{!}}.html`」とすると、末尾の「`.htm`」を「`.html`」に変換できます。「`{{!}}`」の前の部分は正規表現なので、「`\`」や「`.`」にはエスケープ文字「`\`」を前置する必要があることに注意してください。「`{{!}}`」の後の置換文字列は正規表現ではないので、エスケープは必要ありません。

`extattr`は任意の属性を表示するのに使います。複数回指定できます。例えば、文書の更新日時を「`Modified`」というラベルをつけて表示したい場合は「`extattr: @mtime|Modified`」と書き、文書のサイズを「`Size`」というラベルをつけて表示したい場合は「`extattr: @size|Size`」と書きます。

### テンプレートファイル

検索ページの見栄えを決めるためのファイルです。HTMLで、記述してある内容がそのまま表示されます。ただし、「`<!--ESTTITLE-->`」の部分にはページタイトルが挿入され、「`<!--ESTFORM-->`」の部分には検索フォームが挿入され、「`<!--ESTRESULT-->`」の部分には検索結果が挿入され、「`<!--ESTINFO-->`」の部分にはインデックスの情報が挿入されます。CSSやJavaScriptを駆使すれば、かなり自由にユーザインターフェイスをカスタマイズすることができます。

### トップページファイル

検索用CGIスクリプトに最初にアクセスした際、あるいは検査条件を全く入力しないでアクセスした際に表示されるメッセージを記述したファイルです。記述してある内容が検索結果の位置にそのまま挿入されます。デフォルトではHyper Estraierのバナーが記述してありますが、お好みのバナーに変えたり、システムのメンテナンス情報などを記載したりするとよいでしょう。

### ヘルプファイル

入力用フォームの付近にある「`help`」リンクを選択すると表示されるメッセージを記述したファイルです。デフォルトでは検索機能の簡単な使い方が記述してあります。設定によって機能が増減した場合はヘルプも適当に書き換えてください。

### 検索フォームの設置

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`」などが使えます。

### お洒落な入力フォーム

Webサイトを検索する際には、本文もしくはタイトルで絞り込むことが多いでしょう。また、ソート条件にはスコアか日付かサイズを指定することが多いでしょう。そういった典型的な操作を簡単に行なうために、`estseek.cgi`にはWebサイト用の入力フォームの形式が用意されています。設定ファイルの`formtype`の値を「`web`」にすると、Webサイト検索用の入力フォームになります。なお、Webサイトの検索を高速化するには、以下のように属性インデックスを張っておくとよいでしょう。

    estcmd create -attr @title str -attr @mdate seq -attr @size seq casket

ファイルサーバを検索する際には、本文もしくはファイル名で絞り込むことが多いでしょう。また、ソート条件にはスコアか日付かサイズを指定することが多いでしょう。そういった典型的な操作を簡単に行なうために、`estseek.cgi`にはファイルサーバ用の入力フォームの形式が用意されています。設定ファイルの`formtype`の値を「`file`」にすると、ファイルサーバ検索用の入力フォームになります。なお、ファイルサーバの検索を高速化するには、以下のように属性インデックスを張っておくとよいでしょう。

    estcmd create -attr _lpath str -attr @mdate seq -attr @size seq casket

メールボックスを検索する際には、本文もしくはSubject/From/To/Ccの各ヘッダで絞り込むことが多いでしょう。また、ソート条件にはスコアか日付かサイズを指定することが多いでしょう。そういった典型的な操作を簡単に行なうために、`estseek.cgi`にはメールボックス用の入力フォームの形式が用意されています。設定ファイルの`formtype`の値を「`mail`」にすると、メールボックス検索用の入力フォームになります。なお、メールボックスの検索を高速化するには、以下のように属性インデックスを張っておくとよいでしょう。

    estcmd create -attr subject str -attr from str -attr @mdate seq -attr @size seq casket

お洒落な入力フォームはJavaScriptによって実現されているので、JavaScriptをサポートしないブラウザを想定する場合には使わない方がよいでしょう。

### クエリ展開

「go/went/gone/going」「man/men」「歩く/歩い(た)」のような活用や、「center/centre」「F-1/F1」「プロキシ/プロクシ」のような表記揺れや、「lady/madam/gentlewoman」「侍/武者/武士」のような類義語を考慮した検索ができると便利です。例えば、「go」で検索すると、「went」や「gone」や「going」を含む文書もヒットするということです。それには、「`go`」という語が入力された際に、それをアプリケーションが「`go OR went OR gone OR going`」というクエリに展開すればよいことになります。

`estseek.conf`の`qxpndcmd`にコマンドラインを指定することで、任意のコマンドを呼び出すクエリ展開を行うことができます。指定したコマンドには、環境変数`ESTWORD`の値として、検索語が渡されます。検索フレーズに複数の語が指定された場合は、各語に対応してコマンドが複数回呼び出されます。呼び出されたコマンドは、クエリ展開した結果の語を改行区切りで出力します。そのような動作をするコマンドを作っておけば、好きなようにクエリ展開を行うことができます。

WordNetという英語のシソーラスを用いて類義語のクエリ展開をするためのコマンド`estwnetxpnd`が「`/usr/local/share/hyperestraier/filter`」の中にインストールされています。WordNetをインストールした上で、`estwnetxpnd`の絶対パスを`qxpndcmd`の値として設定すると使えるようになります。

「`estcmd extkeys`」でキーワードを抽出してある場合は、「`estcmd words -kt`」で関連語の一覧をダンプすることができます。出力はTSV形式です。第1フィールドはキーワードの文字列で、第2フィールドはその語の頻度です。第3フィールド以降には、関連語の文字列とそのスコアが交互に現れます。この出力をもとにデータベースを作成し、それをクエリ展開のコマンドで利用するとよいでしょう。

### 裏技

属性条件の入力欄に「`gstep=1`」などとすると、N-gramの検査精度を一時的に変えられます。同様に「`tfidf=true`」または「`tfidf=false`」とすると、TF-IDF法の有効無効を一時的に変えられます。「`scan=true`」または「`scan=false`」とすると、検索フレーズの精密検査の有効無効を一時的に変えられます。

検索結果の経過時間表示の右側に「`*`」マークがつくことがあります。これは、インデックス内に削除文書の情報がたくさんあることによって検索処理が非効率になったことを意味しています。頻繁にこれがでるようになったら、インデックスの最適化を行ってください。

## 表示用CGIスクリプト

ここでは、表示用CGIスクリプト`estproxy.cgi`の詳細な仕様を説明します。これを使うと、Googleのキャッシュ機能のように、検索語の部分をハイライトして表示することができます。

### 構成と機能

`estproxy.cgi`が動作するには、`estproxy.conf`という設定ファイルが必要です。設定ファイルの名前はCGIスクリプトの接尾辞を`.conf`に変えたものです。

`estproxy.cgi`は「`/usr/local/libexec/estproxy.cgi`」としてインストールされていますので、それをコピーして利用してください。また、設定ファイルのサンプルが「`/usr/local/share/hyperestraier/estproxy.conf`」としてインストールされていますので、それをコピーして修正すると楽です。

`estproxy.cgi`は、CGIスクリプトとして動作するプロクシです。すなわち、Web上の任意の文書のURLをパラメータとして与えると、ユーザの代理としてその文書のデータを取得し、適当な加工を施した上で、その結果を表示します。取得すべき文書のURLは「`url`」という名前のパラメータとして指定します。HTML以外のメディアタイプの文書もHTMLに変換して表示するのが特徴です。さらに、「`word1`」から「`word32`」までの名前のパラメータによって、ハイライトすべき語句を指定することができます。

対応するプロトコルは、HTTPとFILEです。「`http://`」で始まるURLを指定すると、HTTPプロトコルを用いてそのコンテンツを取得します（今のと頃HTTPSには対応していません）。「`file://`」で始まるURLを指定すると、`estproxy.cgi`が動作するファイルシステム上のファイルを直接読み込んで処理します。この仕組みによって、サーバ上の任意のファイルの内容を加工して表示することができます。

対応するファイル形式は、プレーンテキスト（text/plain）とHTML（text/html）とMIME（message/rfc822）です。それ以外の形式の場合でも、任意の外部フィルタで加工することによって処理することができます。

### 設定ファイルの書式

設定ファイルは、変数名と値を「`:`」で区切った形式の行を並べたものです。「`#`」で始まる行はコメントとして無視されます。デフォルトでは、設定ファイルは以下のような内容になっています。

    #replace: ^http://localhost/{{!}}file:///home/mikio/public_html/
    allowrx: ^http://
    #allowrx: ^file://
    denyrx: /\.
    passaddr: 1
    limitsize: 32
    urlrule: \.est${{!}}text/x-estraier-draft
    urlrule: \.(eml|mime|mht|mhtml)${{!}}message/rfc822
    typerule: ^text/x-estraier-draft${{!}}[DRAFT]
    typerule: ^text/plain${{!}}[TEXT]
    typerule: ^(text/html|application/xhtml+xml)${{!}}[HTML]
    typerule: ^message/rfc822${{!}}[MIME]
    language: 0
    shownavi: 1

それぞれの変数の機能を以下に示します。

- `replace` : URLを変換するための正規表現と置換文字列を「`{{!}}`」で区切って指定します。変換文字列内の「`&`」は一致文字列に展開されます。部分式に展開される「`\1`」から「`\9`」も利用できます。複数回指定できます。
- `allowrx` : 取得することを許可するURLを正規表現で指定します。複数回指定できます。
- `denyrx` : 取得することを禁止するURLを正規表現で指定します。複数回指定できます。
- `passaddr` : 正数なら、クライアントのIPアドレスをX-Forwarded-Forヘッダで通知します。
- `limitsize` : 取得するデータの最大サイズをメガバイト単位で指定します。
- `urlrule` : URLの正規表現とそれに対応するメディアタイプを指定します。この規則はContent-Typeヘッダよりも優先されます。複数回指定できます。
- `typerule` : メディアタイプとそれに対応するフィルタを指定します。メディアタイプは正規表現で指定し、フィルタは文書ドラフト用なら「`[DRAFT]`」とし、プレーンテキスト用なら「`[TEXT]`」とし、HTML用なら「`[HTML]`」とし、MIME用なら「`[MIME]`」とします。複数回指定できます。
- `language` : 好ましい言語を指定します。0なら英語、1なら日本語、2なら中国語、3なら韓国語、4なら未指定です。
- `shownavi` : 正数なら、ナビゲーションバーを表示します。

`allowrx`と`denyrx`の判定は、`replace`を適用した結果に対して行なわれます。`allowrx`と`denyrx`は記述した順番に解釈されます。正規表現における英字の大文字と小文字は区別されません。

### 応用例：HTMLのハイライト表示

`estseek.cgi`の検索結果のページに、該当文書のハイライト表示のリンクをつけてみましょう。`estseek.cgi`と同じ場所に`estproxy.cgi`と`estproxy.conf`も置いてください。あとは、`estseek.cgi`に以下の記述をするだけでOKです。

    ...
    dispproxy: estproxy.cgi
    ...

日本語のページの文字コード認識の精度を向上させるためには、「`language: 1`」も指定するとよいでしょう。また、加工済のページの冒頭にあるナビゲーションバーが不要な場合は、「`shownavi: 0`」にしてください。

### 応用例：メールの表示

`estseek.cgi`によるメールボックスの検索システムで検索の該当文書を表示する際には、該当文書のタイトルからのリンク先と「`[disp]`」のリンク先の双方に`estproxy.cgi`を使ったページのURIを指定すると便利です。ここでは、`estseek.cgi`と`estproxy.cgi`が同じ場所に設置してあり、メールボックスのデータは「`/home/mikio/Mail`」の下にあるものとします。その場合、`estseek.conf`には以下のように記述してください。

    ...
    replace: .*/Mail/{{!}}estproxy.cgi?url=file:///home/mikio/Mail/
    ...
    dispproxy: [URI]
    ...

セキュリティ上の理由から、`estproxy.conf`のデフォルトの設定では「`file://`」によるアクセスは許可していませんので、以下の用に記述してメールボックスの中身のみを表示できるようにしてください。

    ...
    allowrx: ^file:///home/mikio/Mail/
    ...

日本語のメールの文字コード認識の精度を向上させるためには、「`language: 1`」も指定するとよいでしょう。なお、もし「`allowrx: file://`」とやってしまうとサーバ上の全てのファイルが公開されることになるので気をつけてください。

## インデックスの構造

ここでは、Hyper Estraierのインデックスの詳細な構造について説明します。補助インデックスや属性インデックスを用いて検索を高速化する方法についても説明します。

### 基本的な構造

インデックスのディレクトリの中には以下のファイルやディレクトリが格納されます。

- `_meta` : メタデータベース。重複起動防止のロック機構も兼ねます。QDBMのDepotデータベースです。レコードのキーはメタデータの名前で、レコードの値はメタデータの値です。
- `_idx/` : 転置インデックスディレクトリ。中に複数の転置インデックスデータベースファイルを格納します。各々の転置インデックスデータベースはQDBMのVillaデータベースです。レコードのキーはN-gramのトークンの異なり語で、レコードの値は文書IDとスコアとハッシュ値のリストです。
- `_fwm` : 単語リストデータベースファイル。転置インデックスに出現した単語のリストです。QDBMのVillaデータベースです。レコードのキーはN-gramのトークンの異なり語で、値はありません。
- `_aux` : 補助転置インデックスファイル。各登録文書のキーワードのみからなる転置インデックスです。QDBMのVillaデータベースです。レコードのキーはN-gram（または分かち書き）のトークンの異なり語で、レコードの値は文書IDとスコアのリストです。
- `_xfm` : 補助単語リストデータベースファイル。補助転置インデックスに出現した単語のリストです。QDBMのVillaデータベースです。レコードのキーはN-gram（または分かち書き）のトークンの異なり語で、レコードの値はDF（そのトークンを含む文書数）の10進数文字列です。
- `_attr/` : 属性データベースディレクトリ。各登録文書の属性を保持します。QDBMのCuriaデータベースです。レコードのキーは文書IDのint型ネイティブ表現で、レコードの値は属性名と属性値のマップ（CBMAP）を直列化したデータを圧縮したものです。
- `_text/` : 本文データベースディレクトリ。各登録文書の本文を保持します。QDBMのCuriaデータベースです。レコードのキーは文書IDのint型ネイティブ表現で、レコードの値はテキストのリスト（CBLIST）を直列化したデータを圧縮したものです。
- `_kwd/` : キーワードデータベースディレクトリ。各登録文書のキーワードを保持します。QDBMのCuriaデータベースです。レコードのキーは文書IDのint型ネイティブ表現で、レコードの値はキーワードと頻度のマップ（CBMAP）を直列化したデータを圧縮したものです。
- `_list` : 文書リストデータベースファイル。各登録文書とそのURIの関連付けを行います。QDBMのVillaデータベースです。レコードのキーは文書のURIで、レコードの値は文書IDの十進数文字列です。
- `__type_name` : 属性インデックスファイル。typeはデータ型で、nameは16進数エンコードを施した属性名です。typeがseqの場合はQDBMのDepotデータベースで、typeがstrかnumの場合はQDBMのVillaデータベースです。seqでは、レコードのキーは文書IDのint型ネイティブ表現で、レコードの値は属性値です。strとnumでは、レコードのキーは属性値と文書IDの末尾にint型ネイティブ表現を連結したもので、レコードの値はありません。

### 2階層転置インデックス

中核となるデータベースは`_idx`です。これは転置インデックスまたは転置ファイルといわれるデータベースであり、ある語を検索キーにして、その語を含んだ文書の一覧を探す機能を提供します。全ての登録文書に表れる全ての語の出現情報を保持しているので、転置インデックスのサイズはとても大きなものになります。

`_aux`は補助転置インデックスと呼ばれる、登録文書のキーワードのみの出現情報を記録した転置インデックスです。キーワードのみに対象を絞っているので、データベースのサイズが小さく、精度の高い検索結果を生成できる利点があります。その反面、全ての語を保持しているわけではないので、検索漏れが発生する可能性があります。

検索が行われた際には、まず補助転置インデックスに対して検索を行い、そこで十分な件数の結果が得られた場合はその時点で結果を提示します。そこで十分が件数が得られなかった場合はさらにメインの転置インデックスを検索し、その結果を提示します。これにより、大抵の場合は高速に高精度の結果を返すことができますし、検索漏れが起こることもありません。

### キーワードデータベースと類似検索

類似検索を実行すると、候補の各文書の本文を取り出してキーワードを計算してから比較するので、とても時間がかかります。登録文書のキーワードを予め計算してデータベースに記憶しておけば、類似検索を高速に行うことができます。キーワードデータベースはそのためのデータベースです。

`estseek.conf`における`smlrvnum`の値は類似検索の際に抽出するキーワードの数を意味しますが、キーワードデータベースを利用する場合にはその値は無視されます。

### キーワード抽出

`estcmd gather`で文書を登録しただけではキーワードの抽出は行われないので、補助転置インデックスやキーワードデータベースは空のままです。`estcmd extkeys`を実行すると、キーワードを抽出して補助インデックスとキーワードデータベースに登録します。この操作を行わなくても動作に支障はありませんが、検索速度を上げるためにはぜひやっておいてください。特に類似検索と類似隠蔽の速度が劇的に向上します。キーワードの選択にはTF-IDF法を用いますので、インデックスを構築する最後の手順で行った方が精度が安定します。したがって、`extkeys`を含めたインデックスの更新手順は以下のようになります。

    estcmd gather -cl -il ja -sd -cm casket .
    estcmd purge -cl casket
    estcmd extkeys casket

抽出されるキーワードの数のデフォルト値は32個です。「`-kn`」オプションで抽出数は変更できます。増やすとデータベースが大きくなりますが、検索精度は向上します。逆に減らすとデータベースは小さくなりますが、検索精度は低下します。文書ドラフトに予めキーワードを埋め込むには、`%VECTOR`制御命令を用いてください。

デフォルトでは、`estcmd extkeys`はTD-IDFのための文書頻度（DF）のデータを全てメモリ上に展開するので、搭載メモリが少ない環境ではメモリ不足になることが考えられます。その場合は、予めDFのデータを外部データベースに保存しておいて、それを使って`estcmd extkeys`を実行するとよいでしょう。以下のようにしてください。

    estcmd words -dfdb mydfdb casket
    estcmd extkeys -dfdb mydfdb casket

### 分かち書きの利用

キーワードを抽出するために分かち書き器を使うようにすることもできます。`estcmd extkeys`を実行する際に「`-um`」オプションをつけると、字種による分かち書きが行われます。つまり、文字を空白、英数字、漢字、平仮名、片仮名、ハングル、それ以外の記号に分類し、それぞれの連続した部分を単語として切り出します。

    estcmd extkeys -um casket

日本語用の形態素解析器MeCabを分かち書きに利用することもできます。Hyper Estraierをビルドする前の設定で「`./configure --enable-mecab`」として、Hyper EstraierにMeCabを組み込んでおくと、字種による分かち書きの代わりにMeCabが使われます。

なお、形態素解析によるキーワード抽出ではTF-IDFによるスコアの調整は不要ですので、文書の登録とキーワードの抽出を同時に行っても精度を保つことができます。以下のようにします。

    estcmd gather -cl -sd -cm -kn 32 -um casket .

「`-kn`」は抽出するキーワードの数を指定して、「`-um`」は形態素解析器を利用することを指定します。文書の登録時にキーワードも登録した場合、`estcmd extkeys`を実行する必要はありません。ただし、大規模なサイトのインデックスを初期構築する場合、キーワード抽出なしで`estcmd gather`を実行してから、`estcmd extkeys`でキーワードを抽出する方が、全体としての時間は短くなります。差分登録の際には文書登録とキーワード抽出を同時に行った方が高速です。

### 属性インデックス

属性検索は属性データベースにおける全てのレコードを検査するために多くの時間がかかります。属性インデックスを作成すると、検査するレコードを絞り込むことによって属性検索を高速化することができます。属性インデックスは`estcmd create`コマンドで作成します。「`-attr`」オプションで対象となる属性名とデータ型を指定します。例えば@title属性にシーケンシャル型のインデックスを張り、@author属性に文字列型のインデックスを張り、@size属性に数値型のインデックスを張るには、以下のようにしてインデックスを作成します。

    estcmd create -attr @title seq -attr @author str -attr @size num casket

シーケンシャル型の属性インデックスは、文書IDをキーにして属性値を値に持つ構造です。検索時には全てのレコードが検査されますが、属性データベースよりは高速に属性検索が行えるようになります。また、型に依存しないという利点と、ソートも高速になるという利点があります。文字列型の属性インデックスは、昇順（辞書順）の文字列をキーとして文書IDを値に持つ構造です。文字列型の演算子の一部（`STREQ`、`STRBW`、`STROREQ`）がとても高速化されます。それ以外の文字列型の演算子もやや高速化されます。数値型の属性インデックスは、昇順の数値をキーとして文書IDを値に持つ構造です。数値型の演算子の一部（`NUMEQ`、`NUMGT`、`NUMGE`、`NUMLT`、`NUMLE`、`NUMBT`）がとても高速化されます。それ以外の数値型の演算子もやや高速化されます。ひとつの属性に指定できるインデックスはひとつだけです。なお、属性インデックスを張ると文書の更新や削除の処理は少し遅くなります。

文字列型と数値型の属性インデックスが張られている属性に対しては、その値の上位を取得するランキング検索を行うことができます。ランキング検索は、検索フレーズが「`[RANK]`」で始まっている場合に行われます。「`[RANK]`」の後ろには、取得する件数と対象の属性名を空白で区切って指定します。例えば、文書のサイズが小さいものから10件を取得するには、「`[RANK] 10 @size`」と指定します。件数が負数の場合は、順序が降順として扱って絶対値の件数を取得します。ランキング検索は属性検索式でなく検索フレーズに指定することに注意してください。全文検索とランキング検索を同時に行うことはできません。

### 疑似インデックス

文書ドラフトを特定のフォルダに入れておくと、そのフォルダを疑似的なインデックスとして扱い、その中にある文書ドラフトを検索対象に含めることができます。疑似インデックスの検索はgrepと同様の逐次探索で行なわれるので、本当のインデックスに比べてかなり遅いですが、インデックスを作る必要がないというのが便利なところです。疑似インデックスのディレクトリが「`/tmp/pindex`」であったとすると、以下のようにしてそれを検索対象に加えることができます。

    estcmd search -pidx /tmp/pindex casket "unix AND linux"

疑似インデックスを検索対象に加えた場合、本当のインデックスと疑似インデックスのメタ検索が行なわれます。疑似インデックスのみを対象として検索する場合は、空のインデックスとのメタ検索を行なってください。疑似インデックスは複数個指定することもできます。`estseek.cgi`で疑似インデックスを検索対象に加える場合、`estseek.conf`に「`pseudoindex: /tmp/pindex`」といった設定を加えてください。

本当のインデックスに文書を登録する際には、各文書を別個のコネクションで登録するよりも、沢山の文書を1回のコネクションで登録した方が効率的です。したがって、登録すべき文書がある程度の量になるまでは疑似インデックスに入れておき、ある程度の量になったら疑似インデックスの中の文書ドラフトを本当のインデックスに登録して、疑似インデックスを空にするという運用方法も検討する価値があるでしょう。

## 助言

ここでは、アプリケーションとしてのHyper Estraierを活用するためのコツをいくつか紹介します。

### 大規模なインデックスの構築

文書を登録する処理では、インデックスの内部で持っているデータベースに膨大な量の書き込みを行います。データベースを参照するオーバーヘッドを抑えるために、Hyper Estraierは処理中のデータをメモリ上にキャッシュする仕組みを持っています。キャッシュが大きい方が登録処理は高速になりますが、スワップが起きるとかえって効率が落ちますので、実メモリの4割程度の大きさにするとよいようです。例えば1GBの実メモリを搭載しているマシンで作業をする場合、400MB程度が適切でしょう。また、10万件以上の文書を登録する場合、インデックスを作成する際に大規模用のチューニングをするように指定すると処理効率が向上します。

`estcmd`の`-cs`オプションを使うとキャッシュサイズの指定ができます。サイズはメガバイト単位で指定します。デフォルトは64MBです。また、`-xl`オプションや`-xh`オプションを使うと大規模用のチューニングがなされます。つまり、以下のようにして文書を登録するとよいでしょう。

    estcmd gather -cl -il ja -xl -sd -cm -cs 400 casket .

インデックスの最大サイズはおおよそ300GBです。また、対象文書がプレーンテキストの場合、インデックスのサイズは対象文書の容量の50%から200%程度になります。HTMLであれば25%から100%程度です。したがって、一つのインデックスに登録できる文書の総量の目安は、プレーンテキストなら300GB、HTMLなら600GBといったところです。なお、インデックスのサイズは、小さい文書が多数あるよりも、大きい文書が少数ある方が小さくなります。また、日本語の文書よりも英語の文書の方が小さくなります。

100GBを越えるインデックスで補助インデックスを利用する場合、補助インデックスのサイズが2GBを越えてデータベースの更新に失敗する可能性があります。その場合は、ビルド前の設定で「`./configure --enable-vista`」として、Vistaデータベースを組み込んでください。

### 可用性の確保

インデックスを更新している最中にはロックがかかるので、そのインデックスを使った検索はその間はできなくなります。検索システムとしては、その間は停止時間ということになります。それを避けるためには、インデックスのコピーに対して更新を処理を行い、完了したらオリジナルと入れ換えるようにするとよいでしょう。また、インデックスの更新中に不意にシステムが停止するなどしてインデックスが壊れた場合も、複製に対する更新であれば問題がないので安心です。

上述の処理を自動化するには、以下のようなスクリプトを書いておくとよいでしょう。冒頭の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 extkeys /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

実際のところ、`estcmd search`の`-nl`オプションを指定したり、`estseek.conf`の`lockindex`の値を`false`にしたりすれば、更新中でロックされているインデックスに対しても検索を行うことができます。ただし、インデックス内のデータの整合性に関する保証ができませんので、不正な検索結果が返される可能性があります。

インデックスが壊れてしまった場合には、`estcmd repair`を使うと修復できますが、壊れる前の全ての文書とその出現情報が復元できるとは限りません。データの完全性を確保するためにはインデックスを作りなおした方が無難ですが、作りなおしている間がダウンタイムになってしまうのは望ましいことではありません。そこで、`estcmd repair -rsh`で簡易的にインデックスを利用可能な状態にして可用性を確保しておいて、バックグラウンドや別のマシンでインデックスの再構築を行い、完成したら壊れたものと入れ替えるようにするとよいでしょう。

### 文書の削除

`gather`や`purge`を実行する際に「`-cl`」をつけるべきかどうかは運用の仕方によって変わってきます。「`-cl`」をつけた場合は、転置インデックスを部分的に最適化するので、処理がやや重くなります。ただし、明示的に`optimize`を実行しなくても検索の速度や精度が落ちません。

「`-cl`」をつけない場合は、転置インデックスを更新しないで、文書情報に削除マークをつけるだけですので、比較的に軽い処理で済みます。ただし、検索時に無駄な領域を処理することになりますので、検索の速度と精度が少しずつ落ちてきます。それを解消するために、定期的にoptimizeを実行することが必要となります。「`-cl`」をつけないで削除した文書の領域を回収するには、`optimize`以外の手段はありません。

通常の運用では、「`-cl`」をつけて`gather`や`purge`を実行するのがよいでしょう。ただし、とても大量の上書きや削除を行う場合には、「`-c`l」をつけないで`gather`や`purge`を実行してから、`optimize`を実行する方が効率的です。また、可用性の確保の項目で述べたように、インデックスの複製に対して更新する場合にも「`-cl`」をつけない方法が適します。`optimize`をした方がインデックスが小さく保たれるからです。

### 文字化け対策

プレーンテキストの文書や、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）は「`\`」をバックスラッシュとして扱うことが明示されている規格なので、この問題はありません。

### 登録文書の選択

インデックスに登録する文書のファイルを選択する際には、UNIXでは`find`コマンドの出力を`estcmd gather`に読み込ませると便利です。`estcmd gather`は入力ファイル名のところに「`-`」を指定すると標準入力を読み込みます。`find`は非常に高機能で、「`-type f`」というオプションをつければファイル名だけを出力できますし、「`-not -path /secret/`」というオプションをつければ、「`secret`」というディレクトリの中を除外することができますし、その他にも様々なオプションがあります。また、`grep`や`fgrep`や`egrep`といったコマンドで`find`の出力を絞り込むのもよい考えです。

WindowsではUNIXの`find`コマンドに相当する標準の機能はありませんが、`estcmd scandir`を使うと同じようなことができます（「`dir /s /b`」でも大抵のことはできますが）。また、`estcmd regex`は、UNIXの`egrep`コマンドと同じように、ファイル名のリストを正規表現で絞り込むことができます。例えば「`C:\inetpub\wwwroot`」以下にあるHTMLファイルの絶対パスのリストを出力するには、以下のようにします。

    estcmd scandir -tf -pa "C:\inetpub\wwwroot" |
      estcmd regex -ci "\.html?$"

### ファイルプロトコルの問題

検索結果の各文書の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の規格に違反しますが）。これを「`replece`」によってUNCに加工してください。なお、UNCにドライブ文字を含めてはならないということに注意してください。例えば、「`d:\pub`」が「`\\skyhigh\pub\`」として共有されているなら、`estseek.conf`に以下のような設定をします。

    ...
    replece: ^d:\\pub\\{{!}}\\skyhigh\pub\
    showlreal: true
    ...

### Windows用のフィルタ

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であるとわかっているためです。なお、行末の「`^`」はコマンドプロンプトのエスケープ文字です。

なお、Windows上でローカルファイルの登録を行なった場合には、各文書には「`file:///C|/pub/foo/bar.doc`」のようなURI属性が付けられます。これを外部公開用のHTTPのURLに変換するには、「`replace: ^file:///C\|/pub/{{!}}http://estraier.gov/`」などとしてください。メタ文字である「`|`」に一致させるには「`\|`」としてエスケープすることが必要です。

### フィルタの作り方

`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を使ったプログラミングをすれば、最も強力なアプリケーションを作ることができるでしょう。

### ジャンルによる絞り込み

`estcmd`と`estseek.cgi`には複数のインデックスを横断的に検索する機能はありません（APIを使えば可能ですが）。したがって、一括で検索するには、異なる種類のデータをひとつのインデックスに格納して、ジャンル属性をつけることによって区別するとよいでしょう。例えば、メールとWebコンテンツをジャンル分けして登録するには、以下のようにします。最初にインデックスを作る時だけ`estcmd create`で属性インデックスを張るのがポイントです。

    estcmd create -attr @genre str casket
    estcmd gather -fm -il ja -aa @genre mail casket /home/mikio/mailbox
    estcmd gather -fh -il ja -aa @genre web casket /home/mikio/public_html

`estseek.cgi`においては、`estseek.conf`の`genrecheck`属性を設定することによって、検索対象となるジャンルをチェックボックスで選んで検索することができます。例えば、上記のインデックスに対しては以下の設定をするとよいでしょう。

    genrecheck: mail{{!}}メール
    genrecheck: web{{!}}Webコンテンツ

### インクリメンタル検索と完全N-gram方式

入力フィールドに文字を打ち込む毎に結果の画面が更新される、いわゆるインクリメンタル検索を行うこともできます。それには、以下の手順を実行してください。

- estcmd gatherでインデックスを作る際に、-apnオプションをつけます。
- `/usr/local/share/hyperestraier/increm/' 以下にあるファイル群をestseek.cgiのあるディレクトリにコピーします。
- estseek.tmplの中の「<!--ESTFORM-->」を削除します。
- コピーしたestseek-frame.htmlにブラウザでアクセスします。

`-apn`オプションは、完全N-gram方式のデータベースを作ることを指定します。完全N-gram方式とは、ヨーロッパ系の言語を解析する際にもN-gram方式を適用するものです。この指定はデータベースを作成する時にしかできません。データベースを作成した後に方式を変更することはできないということです。完全N-gramでなくてもインクリメンタル検索は可能ですが、英文だと単語毎でしか文書がヒットしないので多少不便になります。なお、完全N-gram方式の欠点は、インデックスのサイズが大きくなることと、関連文書検索の精度が下がることです。したがって、インクリメンタル検索を使わない場合は通常の方式が推奨されます。

### FastCGI

裏技の範疇に入りますが、`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サーバおよびNFSクライアントがロックをサポートしている必要があります。21世紀の実装であれば大抵はロックをサポートしているでしょう。また、NFSサーバのプロセッサとNFSクライアントのプロセッサのエンディアンが一致していることが必要です。

以上の条件を満たしているならば、NFSを使って複数のマシンでインデックスを共有することができます。並列化に関する条件は単一のマシンを使っている場合と同じです。すなわち、あるプロセスがライタで接続している間は他のプロセスはリーダでもライタでも接続できず、あるプロセスがリーダで接続している間は他のプロセスはリーダであれば接続できます。

### WWWOFFLEのキャッシュの検索

プロクシサーバ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ライフの一助となるでしょう。

### 圧縮方式の選択

デフォルトではインデックスの各データベースはZLIBを用いて圧縮されますが、ビルド前の設定で「`./configure --disable-zlib`」とすると、圧縮をしないようにすることができます。同様に、「`./configure --enable-lzo`」とするとZLIBの代わりにLZOを用いるように、「`./configure --enable-bzip`」とするとZLIBの代わりにBZIP2を用いるようにすることができます。ただし、転置インデックスディレクトリ（`_idx/`）の圧縮に関しては、QDBMが該当の圧縮方式をサポートしていない場合は非圧縮となります。

圧縮方式の選択によって、インデックスのサイズと構築にかかる時間は大きく変わります。以下にインデックスのサイズと構築時間の参考値を示します。対象文書はWikipedia日本語版から無作為に抽出した50000件の文書（プレーンテキストとして130.69MB）で、実行環境のCPUはPentium4の1.7GHzで、搭載メモリは1GBで、割り当てたキャッシュサイズは512MBです。

| _idx | _attr | _text | 合計 | 時間
--- | --- | --- | --- | --- | ---
非圧縮 | 189.25MB | 21.82MB | 138.08MB | 349.16MB | 481秒
LZO | 169.90MB | 18.59MB | 86.74MB | 275.24MB | 553秒
BZIP2 | 146.89MB | 20.15MB | 64.79MB | 231.83MB | 820秒
ZLIB | 139.78MB | 17.09MB | 65.97MB | 222.85MB | 602秒

特別な理由がない限りはZLIBを使うことを推奨します。更新が非常に頻繁な場合は、処理速度の速いLZOを使ってもいいでしょう。非圧縮やBZIP2を使うべき状況はまずないでしょう。なお、検索にかかる時間はどの方式でも大差ありません。

スコアの精度を何バイトにするかによってもインデックスのサイズと構築時間は変わります。以下に参考値を示します。圧縮方式はZLIBとします。

| _idx | _attr | _text | 合計 | 時間
--- | --- | --- | --- | --- | ---
0バイト | 117.10MB | 17.09MB | 65.97MB | 220.17MB | 530秒
1バイト | 139.78MB | 17.09MB | 65.97MB | 222.85MB | 602秒
4バイト | 170.23MB | 17.09MB | 65.97MB | 253.30MB | 670秒

常に順序指定式を使う場合はスコアは不要ですので、精度を0バイト（つまり記録しない）にしてもいいでしょう。そうでない場合は1バイト（デフォルト）にするのがいいでしょう。4バイトにしても体感的な精度はそれほど向上しません。

### 自然順序のカスタマイズ

順序指定式を何も指定しない場合の検索結果の表示順序を自然順序と呼ぶことにします。デフォルトでは自然順序はスコア（検索語の出現数）の降順です。ところで、順序指定式を使って検索結果を並べ替えた際には、自然順序で並べた場合に比べてかなり遅くなるという欠点があります。そこで、スコアとして属性の値を持たせて、順序指定式を使わずに、属性値によって並び替えた検索結果を得られるようにしてみましょう。

スコアとして属性値を使うには、`estcmd`でインデックスを作成する際に、`-sa`オプションを付けてスコアの精度を確保した上で、文書を登録する際に`-ss`オプションでスコアの値となる数値型の属性の名前を指定します。例えば、文書のサイズを自然順序にするには、以下のようなコマンドを実行してください。

    estcmd gather -cl -il ja -sa -ss '@size' -sd -cm casket .

上記のようにインデクシングを行った場合、検索時に順序指定式を指定しない場合は、該当文書がサイズが大きい順に並べられます。サイズが小さい順に並べたい場合は、順序指定式として、「`[SCA]`」を指定してください。この演算子だけは順序指定式であっても属性を参照しないので速度が落ちません。文書ドラフトに予め代替スコアの指定を埋め込むには、`%SCORE`制御命令を用いてください。

登録時に文書に付与されたスコアは後から変更することはできません。`estcmd edit`で属性の値を変更してもそれはスコアに反映されないということです。スコアを変更したい場合は、いったんその文書をインデックスから削除してから再登録してください。

### インデックスのマイグレーション

Hyper Estraierのバージョンによってインデックスの形式が異なる場合があります。今後はフォーマットをなるべく変更しないようにするつもりですが、万が一変更された場合には、既存のインデックスのデータをダンプしておき、そのデータを新しいバージョンのHyper Estraierに読み込ませるとよいでしょう。この手法は、バージョン間のマイグレーションだけでなく、エンディアンの異なるプラットフォーム間でのマイグレーションにも有効です。

データをダンプするには、以下のようなコマンドを実行します。

    estcmd search -max -1 -dd casket [UVSET]

すると、カレントディレクトリに`00000001.est`、`00000002.est`、`00000003.est`…といった名前のファイル群が生成されます。それぞれのファイルはインデックス内の個々の文書の文書ドラフトです。そして、そのファイル群を新しい環境に移して、`estcmd gather`で読み込ませるだけです。

## よく聞かれる質問

Q. 「Hyper Estraier」はどう発音すればよいですか？
  A. 作者は「ハイパーエストレイア」と発音しています。ちなみに、「estraier」は古いフランス語で「迷う」とか「はぐれる」とかいう意味の言葉ですが、本当の読み方はよく分かりません。

Q. 「Hyper Estraier」と「HyperEstraier」はどちらが正しいですか？
  A. プロジェクト名としては「Hyper Estraier」が公式の名前です。パッケージ名としては「hyperestraier」が使われます。「HyperEstraier」はプログラム内の識別子やHTTPのユーザエージェント名として使われることがあります。

Q. コマンドの実行例で出てくる「casket」って何ですか？
  A. 英語で「棺桶」という意味の言葉です。「死体（corpse）を入れる箱」と「文例集（corpus）を入れる箱」を掛けているのですが、なかなか気づいてもらえません。

Q. Windows上で動きますか？
  A. 動きます。バイナリパッケージをダウンロードしてください。

Q. ビッグエンディアンもしくはリトルエンディアンのマシン上で動きますか？
  A. はい。どちらでも動作します。ただし、双方でインデックスを共有することはできません。

Q. 64ビットのプロセッサで動きますか？
  A. はい。問題なく動作します。

Q. EstraierとHyper Estraierを同一システムに共存させることは可能ですか。
  A. はい。可能です。コマンド名やライブラリ名などが重複しないように配慮していますので、互いに衝突することはありません。

Q. Estraierとインデックスの互換性はありますか？
  A. いいえ。互換性はありません。

Q. PDFは扱えますか？
  A. はい。適切なフィルタを組み合わせれば可能です。ただし、暗号化されていたり文字が画像として保存されているPDFからはテキストを抽出できません。テキスト抽出禁止のフラグが立っているだけなら、pdftotextをハックすれば何とかなるらしいです。

Q. 私の商用製品でHyper Estraierを使ってよいですか？
  A. はい。Hyper Estraierを商用の製品やサービスで利用することは全く問題ありませんし、ライセンス料も一切かかりませんし、利用することを作者に報告する必要もありませんし、利用していることをどこかに明記する必要もありません。なお、LGPLにおいては、ライブラリをスタティックリンクした製品を配布するかダイナミックリンクにしてアプリケーションとライブラリを別途に配布するかは本質的な問題ではありません。どちらにせよHyper Estraier自体を無改変で配布するのであればソースコード公開の義務は発生しません。たとえHyper Estraierを改変したとしても、改変したHyper Estraier自体のソースコードを公開すればよいだけで、あなたの製品のその他のモジュールのソースコードを公開する必要はありません。詳しくは「`COPYING`」ファイルを読んでください。

Q. ビルドに失敗したのですが、なぜですか？
  A. QDBMとlibiconvとzlibのバージョンが適切かどうか調べてください。Mac OS Xの場合は「`make mac`」、HP-UXの場合は「`make hpux`」を実行したか確認してください。ビルドに必要なコマンド（`ar`や`ld`など）がパスに含まれているかどうか確認してください。それでもダメなら、メーリングリストか作者に報告してください。

Q. 設置したestseek.cgiにアクセスすると「Internal Server Error」になってしまいます。どうすればいいですか？
  A. estcmdが実行できて正常にインデックスが作成できているなら、インストールはうまくいっているはずです。おそらく問題は、Webサーバを実行しているユーザのライブラリ検索パスにlibestraier.soやlibqdbm.soなどのある場所が含まれていないことです。環境変数LD_LIBRARY_PATH（Mac OS Xの場合はDYLD_LIBRARY_PATHで、Windowsの場合はPath）を適切に設定してください。

Q. インデックスが壊れてしまいましたが、修復するにはどうすればいいですか？
  A. `estcmd repair`を使うと修復できます。しかし、インデックスが壊れた時に登録していた文書は消失している可能性があることに気を付けてください。万一の事故に備えて定期的にバックアップを取るのは大人としてのマナーです。

Q. バグを発見しました。
  A. できるだけ対応したいので、メーリングリストか作者に報告してください。その際に、開発環境、実行環境、再現手順、エラーメッセージ、ログなど、できるだけ詳細なデータがあると助かります。なお、`estcmd`を実行する際に環境変数`ESTDBGFD`の値にファイルディスクリプタを設定しておくと、そこにエラーが起きた場所が出力されるようになります。

Q. Hyper EstraierやEstraierの他にも有用な全文検索システムはありますか？
  A. たくさんあります。オープンソース製品だと、海外ではApache Lucene、Xapian、GNU mifluz、Harvest、Swish-e、ht://Dig、mnoGoSearchなどが有名です。日本だとNamazu、Rast、Senna、GETAなどが有名です。