Java

Lucene3.1 メモその5 – 数値型のフィールドを設定する

基本その5,数値型フィールドの保存

Luceneのインデックスは基本的にStringかbyte[]のみを保存するようになっているようです。数値型を保存する場合、String.valueOf(number)で文字列に変換して保存してもいいですが、辞書順にソートすると 1,10,11,2,3,4…などと人間味のない順番になってしまう可能性があります。
そこで数値型を保存する場合はNumericFieldというクラス(Lucene2.9より導入)を使います。

サンプルプログラムでは以下のことをやっています
・メモリ上(RAMDirectory)にインデックスを格納
・それぞれ8,9,10,11の値をもつドキュメントを4つ追加
・ソートキーとなるフィールドを指定して検索
・自然な順番でソートされていることを確認

NumericUtilsというユーティリティクラスを使って数値を文字列、またはその逆に変換しても良いみたいです(NumericFieldの内部でNumericUtilsを使っている)。

    @Test
public void index() throws Exception {
RAMDirectory directory = new RAMDirectory();
Analyzer analyzer = new StandardAnalyzer(Version.LUCENE_31);
IndexWriterConfig iwc = new IndexWriterConfig(Version.LUCENE_31, analyzer);
IndexWriter writer = new IndexWriter(directory, iwc);

for (int i = 8; i < 12; i++) {
Document doc = new Document();
doc.add(new NumericField("int_field", Field.Store.YES, true).setIntValue(i));
System.out.println(doc);
writer.addDocument(doc);
}
writer.commit();

IndexReader reader = IndexReader.open(writer, true);
IndexSearcher searcher = new IndexSearcher(reader);
TopDocs td = searcher.search(new MatchAllDocsQuery()
, 1000, new Sort(new SortField("int_field", SortField.INT)));
assertThat(td.totalHits, is(4));
assertThat(searcher.doc(td.scoreDocs[0].doc).get("int_field"), equalTo("8"));
assertThat(searcher.doc(td.scoreDocs[1].doc).get("int_field"), equalTo("9"));
assertThat(searcher.doc(td.scoreDocs[2].doc).get("int_field"), equalTo("10"));
assertThat(searcher.doc(td.scoreDocs[3].doc).get("int_field"), equalTo("11"));

reader.close();
writer.close();
searcher.close();
directory.close();
}

すぐ試せるmavenベースのソースコードはここに置いてあります。
Lucene3.1、JUnit4.8を使っています。

関連記事:
Lucene/Solr 3.1 リリース | 関口宏司のLuceneブログ
Lucene3.1 メモその1 – ドキュメントのインデックスを作成して検索する – 侍ズム
Lucene3.1 メモその2 – ドキュメントを追加する – 侍ズム
Lucene3.1 メモその3 – ドキュメントを更新する – 侍ズム
Lucene3.1 メモその4 – 検索結果をソートする – 侍ズム
Lucene3.1 メモその6 – 日本語のドキュメントを検索する – 侍ズム
Lucene3.1 メモその7 – 形態素解析をして日本語のドキュメントを検索する – 侍ズム