Zend_Search_Luceneは日本語では使い物にならなかった話
結論から先に言うと、設定は簡単なんですけど、
形態素解析もN-GramでもないAnalyzerしかついてないので、思った言葉で全然ヒットせず、
自分でAnalyzer書かないと使い物にはならなそうです。
簡単な使い方はZendFrameworkに同梱されていますし、
ZendFramework/demos/Zend/Search/
マニュアル見ても行けますが、書いてみます。
まずZend_Search_Luceneの前提ですが、JavaのLuceneと同じフォーマットのindexを作ったりそこから検索することができます。
Lucene自体は不要です。Microsoft Wordで作ったファイルをOpenOfficeからでも読み書きできる、というのと同じイメージです。
それと、範囲検索、あいまい検索はまだ正式版の出ていないZendFramework 1.5で搭載予定とのことです。
では使い方。
デフォルトだとASCIIなアナライザーなので、日本語をうまく索引に入れてくれません。
UTF-8使う物に書き換えます (しかし本当はこれも使いものにならない)。
Zend_Search_Lucene_Analysis_Analyzer::setDefault(new Zend_Search_Lucene_Analysis_Analyzer_Common_Utf8());
次に検索indexを取得。空ディレクトリーに対して、初回はcreateすればok。
ただし、索引のlockに失敗した場合に例外が飛ぶこともあるようです。
// 新規作成または取得
$searchIndex = Zend_Search_Lucene::create($luceneIndexDir);
$searchIndex = Zend_Search_Lucene::open($luceneIndexDir);
// $dataの中身を索引に追加
set_time_limit(0);
$encoding = 'UTF-8';
foreach ($data as $datum)
{
// 大文字小文字を区別したくないので、小文字で統一
// @see http://framework.zend.com/manual/ja/zend.search.lucene.charset.html#zend.search.lucene.charset.utf_analyzer
$doc = new Zend_Search_Lucene_Document();
$doc->addField(Zend_Search_Lucene_Field::UnIndexed('id', mb_strtolower($datum->getId()), $encoding));
$doc->addField(Zend_Search_Lucene_Field::Text('content', mb_strtolower($datum->getContent()), $encoding));
$searchIndex->addDocument($doc);
}
// 追加、変更処理後にcommitするのが好ましいらしい
// @see http://framework.zend.com/manual/ja/zend.search.lucene.advanced.html#zend.search.lucene.advanced.static
$searchIndex->commit();
// $textを検索
$encoding = 'UTF-8';
Zend_Search_Lucene_Search_QueryParser::setDefaultEncoding($encoding);
// parseさせ、だめなら単一の文字列として検索する
try
{
$query = Zend_Search_Lucene_Search_QueryParser::parse($text);
}
catch (Zend_Search_Lucene_Search_QueryParserException $e)
{
$term = new Zend_Search_Lucene_Index_Term($text);
$query = new Zend_Search_Lucene_Search_Query_Term($term);
}
$hitDocuments = $searchIndex->find($query);
echo count($hitDocuments);
foreach ($hitDocuments as $hitDocument)
{
$messages[] = $hitDocument->id . $hitDocument->content;
}
それぞれ、$encodingを追加しないと、文字化けします。
localeも設定しないとと言う情報もあるのですが、WindowsだとUTF-8のlocaleにできないですよね?
なので、ここではJapanese_Japan.932のままです。
これで、いちおう日本語で検索できるのですが、なんかあまりヒットしません。
この原因は、Lukeかなんかでindexを覗いて見るとわかります。
・・・なんか文章まるまるtokenになってたりするよなんじゃこりゃ?
Zend_Search_Lucene_Analysis_Analyzer_Common_Utf8クラスのソースを見ると、
アルファベットかどうかの区切りのところでtokenを区切ってるんですよね(T-T)。
せめて、漢字・ひらがな・カタカナくらいで分けてくれれば・・・。
と言うわけで、ガッツのある方は、analyzer作って公開してください。
PHP_MeCab
PHP Namazu/Chasen
Yahoo! テキスト解析Webサービス
ない方は、ほかを当たった方が良いかも。
MySQLで全文検索 - FULLTEXTインデックス
MySQL FULLTEXT + Ngram
Senna
Trackback URL for this post:
以前、Zend_Search_Luceneには日本語で使えるアナライザーが入っていなくて使い物にならない、と書きましたが、1.5.2でも状況は同じです。
話にならないので、ちょっとした息抜きに日本語テキ

Contributerへのお誘い
Zend_Search_Luceneは日本語では使い物にならなかった話、を拝見いたしました。
CLA契約が必要になりますが、
ぜひZend Frameworkのソース修正に参加してみませんか。
CLA契約についてはこちら
http://framework.zend.com/wiki/display/ZFPROP/Contributor+License+Agreement