ページ

2011年11月9日

LuceneのFastVectorHighlighterを使う

Luceneで検索結果のハイライト表示はorg.apache.lucene.search.highlight.Highlighterを使っていました。このヒトは、CJKAnalyzerとかN-Gramのアナライザと一緒に使うと、ハイライト部分が直感に反するモノになっていました。下の図は、「アリエル」と「情報」で検索したときのハイライト表示です。FastVectorHighlighterを使えば、このようなハイライトの仕方はなくなるって噂では聞いていました。ハイライトが変わるだけじゃなくスピードも改善するらしいです。けれども、使い方がよく分かりませんでした。でも、そんなことも言っていられないのでちょっとまじめに調べてみました。

まずは、FastVectorHighlighterを使うためのimportです。
import org.apache.lucene.search.vectorhighlight.*; 

Javaはタイピングの練習にちょうどいいですね。ウソです。Eclipseに補完してもらいました。楽ちんです。
FastVectorHighlighterを使ってハイライト表示するためには、インデックス作成時に各termの位置情報を保存するように指定しなければいけません。つまり、既存のインデックスはアップデートしないとFastVectorHighlighterのハイライト表示は使えません。
位置情報を保存するには、FieldにField.TermVectorで指定します。このひとは、NO,とWITH_POSITION, WITH_POSITION_OFFSET, YESってあります。YESを指定しておけばいいだろうと、安易に考えてはいけません。YESだとFastVectorHighlighterは使用できません。ここは、WITH_POSITION_OFFSETを指定します。これで、位置情報がちゃんと保存されます。WITH_POSITIONだけで大丈夫なのかどうかは試していません。Javaのコードはこんな感じ。
document.add(new Field("content", content, Store.YES, Field.Index.ANALYZED, Field.TermVector.WITH_POSITIONS_OFFSETS)); 

さて、インデックスに必要な情報が保存されたので、実際にスニペットを取得します。
FastVectorHighlighter highlighter = new FastVectorHighlighter(); 
String[] snippet_fragments = highlighter.getBestFragments(highlighter.getFieldQuery(query), indexReader, documentId, "content", 32, 5);

あらかじめインデックスに位置情報を保存するっていうことを知っていれば大したことないコードです。位置情報を保存していないと、フラグメントが取得できなくって、なぜだろうってはまります。
取得した断片はハイライト部分はbタグで囲まれています。FragmentBuilderで指定することでハイライト部分のタグをカスタマイズできます。でも、めんどいので書きません。

でわでわ


0 件のコメント: