FrontPage

Luceneとは?

Jakarta Luceneは完全にJavaで書かれたハイパフォーマンスな全文検索エンジンのライブラリです。Luceneは全文検索が必要なアプリケーションに適しています。特にクロスプラットフォーム性を重視する場合は有用です。Javaの検索エンジンとしては、Namazu on Java2等もありますが、Namazu on Java2はライセンスがGPLで公開されており、(GPLが悪いという訳ではありませんが...)Namazu on Java2をアプリケーションに組み込むと開発したアプリケーションにもGPLが適用されます。LuceneはApache Software Licence 2.0で配布されており、アプリケーションに組み込んでもソースコードを公開する必要はありません(もちろん公開しても構いません)。LuceneはEclipseのヘルプの検索等、身近で利用されています。Luceneの優秀さは世界中の全文検索エンジンの研究者が認めるところであり、.NET、Ruby、Python、Perl、C++等の他の言語にもポーティングされています。

 

Luceneの原作者であるDoug Cuttingさんは、以前はXeroxのPalo Alto 研究センター(PARC), Apple, Excite@Homeで検索エンジンを書いていました。そして、いくつかの情報検索システムに関する 論文や特許を書いています。ちなみに、Luceneは、ルシーン(Luceen)と発音します。

参考文献

全文検索エンジンとは?

馬場 肇 さんの「日本語全文検索エンジンソフトウェアのリスト」を参照

 

http://www.kusastro.kyoto-u.ac.jp/~baba/wais/other-system.html#fulltext_retrieval

日本語環境について

残念ながら、Lucene自身は日本語を正しく扱うことはできません。一見正しく動いているように見えても、一部の文字がリジェクトされ正しくインデックスが作成されません。理由はアナライザというモジュールが正しく動作しないためです。アナライザは文書から単語を切り出すのですが、英語の場合単語が空白に区切られているんで、簡単に単語を抽出することができます。例えば、"I love Lucene"という文書があった場合、簡単に"I"、"love"、"Lucene"を切り出すことができます。しかし、日本語の場合は、"私はルシーンが好きです"となってしまい、単語の区切り目を検出することが困難です。

 

Luceneは柔軟なプラグインアーキテクチャによって構成され、アナライザを自由にカスタマイズ可能となっています。日本語で利用できるアナライザを作成することにより、日本語で利用できるようになります。日本語で利用できるアナライザは現在の所、次の3つがあります。

JapaneseAnalyzer

日本語の分かち書きを行う手法の一つとして形態素解析があります。形態素解析は、例えば、

Luceneは優秀な全文検索エンジンです。

という文書が合った場合、

| Lucene | は | 優秀な | 全文検索 | エンジン | です |

と単語毎に区切ります。また、名詞、動詞等の品詞情報も同時に取得することができます。JapaneseAnalyzerでは、文書を単語に分割し、各単語の中で検索に重要でない単語を除いて登録します。例えば、助詞(は)や助動詞(です)等は上記の文書にとって重要でない単語なので省きます。残った単語をインデックスに登録します。

CJKAnalyzer

CJKAnalyzerは、中国語、日本語、韓国語に対応したアナライザです。CJKAnalyzerはbi-gramという手法を利用してCJKブロックの文書を単語に分割します。例えば、上記の例文は、

| Lucene | は優 | 優秀 | 秀な | な全 ...

のように、日本語の部分が2文字づつずらした形で単語が切り出され登録されます。CJKAnalyzerは登録するインデックスの数が多くなるので、インデックスの辞書のサイズが多くなるのと、検索時にノイズが引っ掛かり易くなるという特徴があります。また、1文字の単語で検索したい場合、検索できないという問題もあります。しかしながら、これ一つで世界中の全ての言語をサポートできるのが大きな魅力です。

NutchAnalyzer

NutchAnalyzerはLuceneをベースとした全文検索エンジンNutchで利用されているアナライザでuni-gramという手法を利用したアナライザです。

| Lucene | は | 優 | 秀 | な | 全 ...

と一文字づつ文字を切り出します。bi-gramと比べると一文字の単語が検索できないということはありませんが、検索結果にノイズが混じりやすくなり、インデックスのサイズも大きくなります。

セットアップ

さて、ではLuceneを早速使ってみましょう。 ここでは、JapaneseAnalyzerを例にLuceneの利用方法を解説します。LuceneとJapaneseAnalyzerの利用には、次のソフトウェアが必要となります。

  • Apache Ant
  • Perl(Windowsの場合ActivePerl/Cygwinなど...)
  • Sen
  • Lucene-ja

まずは、各ソフトウェアをセットアップしていきましょう。既にご存知の方は適宜読み飛ばして下さい。

Antのインストール

Apache Antのサイト

 

http://ant.apache.org/bindownload.cgi

 

からAntの最新版をダウンロードして適当なディレクトリに展開してインストールしてください。インストール後例えば、C:\ant-1.6.2にインストールした場合、環境変数のPATHにC:\ant-1.6.2\binを追加して下さい。

Senのインストール

Java.NETのSenのプロジェクト

 

https://sen.dev.java.net/servlets/ProjectDocumentList?folderID=755&expandFolder=755&folderID=0

 

からsenをダウンロード、適当なディレクトリで解凍(例えばc:\)し、dicディレクトリで次のようにして辞書を作成します。なお、辞書の作成にはperlが必要なので、Windows環境ではcygwinもしくはActivePerlをインストールしておいて下さい。

c:\sen-1.0\dic> ant -Dperl.bin=c:/cygwin/bin/perl.exe 

辞書は、NAISTで配布しているIPADICを利用します。上記コマンドにより自動的にIPADICをダウンロードしSen用の辞書を作成します。

Luceneのインストール

上記のJava.NETのSenのプロジェクトからlucene-jaをダウンロードし、解凍します。lucene-javaには、Luceneが含まれているため、本家のLuceneをダウンロードする必要はありません。

デモプログラムの実行

LuceneにはファイルとHTMLからインデックスの生成と検索をデモプログラムが含まれています。ここでは、デモプログラムの利用方法を説明します。

環境変数設定

全てインストールが完了したら、環境変数の設定を行います。

  1. SEN_HOMEをsenをインストールしたディレクトリに設定
  2. LUCENE_HOMEをlucene-jaをインストールしたディレクトリに設定
  3. PATHに%LUCENE_HOME%\binを追加 例えば、次のようになります。
    C:\> SET SEN_HOME=C:\sen-1.0
    C:\> SET LUCENE_HOME=C:\lucene-ja-1.4
    C:\> SET PATH=%PATH%;%LUCENE_HOME%\bin

インデックスの作成

Luceneを使って検索するには、まずはインデックスに検索対象にしたいコンテンツを 登録します。インデックスの生成には、mktextndex.batもしくはmkhtmlindex.batを利用します。mktextindex.batはテキストファイルからインデックスを作成します。mkhtmlindexはご想像の通りHTMLファイルからインデックスを作成します。オプションは次の通りです([]内のオプションは省略可能)。

mkhtmlindex.bat [-create] -index <インデックスのディレクトリ> <コンテンツのディレクトリ/ファイル>

インデックスのディレクトリにディレクトリもしくはファイルで指定したコンテンツ のインデックスが生成されます。-creataは新規にインデックスを作成するときだけ利用して下さい。一度作成したインデックスには、後からコンテンツを追加することができます。

検索

検索するには、search.batにインデックスのディレクトリを指定して実行します。

search.bat <インデックスのディレクトリ>

Webアプリケーションからの利用

Lucene API

はっきりいって、付属のデモツールでできることは大したことはありません。Luceneの凄い所は、検索サービスを作成するために検索エンジンのプリミティブなAPIを提供しているところです。lucene-jaのorg.apache.lucene.demoパッケージにデモプログラムが入っていますので、そちらも参考にして下さい。

インデックス作成

インデックスを作成するには、下記の手順で行います。

  1. インデクサ(IndexWriterオブジェクト)の生成
  2. 文書の登録

    下記の処理を各文書毎に繰り返す

    1. 文書のフェッチ
    2. フィルタ処理
    3. ドキュメント(Documentオブジェクト)の登録
  3. インデクサのクローズ

さて、では実際にコードみながら、上記の処理をみていきましょう。

1.インデクサの生成

インデクサの作成は、IndexWriterインスタンスの作成によって行います。

public IndexWriter IndexWriter(String index,Analyzer analyzer, boolean create)
  • index: インデックスを作成するディレクトリ
  • analyzer: アナライザ。日本語を利用する場合は、JapaneseAnalyzerを指定します。
  • create: インデックスを新規に作成する場合はtrueを、既存のインデックスに文書を追加する場合はfalseを指定します。

例えば、

 System.property("sen.home", "C:/sen-1.0");
 IndexWriter writer = new IndexWriter("C:/home/okamoto/index", new JapaneseAnalyzer(), true);

のように指定すると、/home/okamoto/indexに新規にインデックスを作成します。なお、JapaneseAnalyzerを利用する場合は、システムプロパティのsen.homeにSenをインストールしたディレクトリを指定して下さい。

2.文書の登録

  • フェッチ 文書のフェッチでは、登録対象のファイルを取得します。ここでは詳細は省略しますが、例えば下記のようにすると、あるディレクトリにあるファイルの一覧を取得できます。
      List list = ..
      String[] files = new File("c:\html").list();
      for (int i = 0; i < files.length; i++) {
        list.add(new File(files));
      }
  • フィルタ HTML文書やPDFの場合、そのままドキュメントをインデックスにすると、余分な文字(例えば、HTMLタグ)が混入したり、そもそも文書を抽出できなかったりします。そこで、フィルタ処理によって、インデックスに登録する文書を抽出します。ここでは詳細な処理は省略します。Lucene-ja付属のHTMLJDocuemnt等を参考にして下さい。
  • ドキュメント登録 テキスト文書の登録を例に以下に示します。基本的には、Documentクラスのインスタンスに必要な情報を加えてIndexWriterで書き込みます。
       File f = new File("hoge.html");
       Reader reader = 
                 new BufferedReader(
                        new InputStreamReader(
                           new FileInputStream(file),"Windows-31J));
    
       Document doc = new Document();
    
       // path属性にパス名を設定
       doc.add(Field.Text("path", f.getPath()));
    
       // modified属性にファイルの最新の更新時刻を設定
       doc.add(Field.Keyword("modified",
                             DateField.timeToString(f.lastModified())
                            )
               );
    
       // charset属性にキャラクタセットを設定
       doc.add(Field.Text("charset", charset));
    
       // contents属性にドキュメント本体のストリームを設定
       doc.add(Field.Text("contents", reader));
        
       // ドキュメントの書き込み
       writer.addDocument(doc);

ここでは、フィルタによって抽出したテキスト文書を検索エンジンのインデックスに登録します。

3.インデクサのクローズ

全てのドキュメントの登録が修了したらインデクサをクローズします。クローズするときは、インデクサの最適化を行ってからクローズします。

writer.optimize();
writer.close();

検索

インデックスを作成したら、次のようにして検索を実行します。

     //初期化処理
     System.setProperty("sen.home",...);
     Searcher searcher = new IndexSearcher("C:/home/okamoto/index");
     Analyzer analyzer = new JapaneseAnalyzer();

     String q = "検索キーワード";

     //クエリ生成
     Query query = QueryParser.parse(q, "contents", analyzer);

     // 検索実行&結果取得
     Hits hits = searcher.search(query);
 
     for (int i = 0; i < hits.length(); i++) {
            // i番目にヒットした文書を取得
	    Document doc = hits.doc(i);
            // 文書登録で設定した属性を取得
            String path = doc.get("path");
            String charset = doc.get("charset");
     }

Nutchの利用

LuceneにPDF/Word/HTML用のフィルタとクローラを追加し、簡単に検索サービスを提供できるようにしたのがNutchです。Nutchは、Google等の大規模な検索エンジンと同様に分散アーキテクチャを採用しており、毎月1億ページ以上のページをインデックスに追加でき、1秒間に1000件以上の検索性能を得ることができると言われています。

辞書のカスタマイズについて

Senでは、奈良先端技術大学のIPADICを形態素解析用の辞書として利用しています。辞書をカスタマイズされたい方は、IPADICのマニュアル http://chasen.aist-nara.ac.jp/stable/doc/ をご覧ください。

その他

コメントなどありましたらお願いします。