Luceneは当初からバイナリデータをインデックスに登録できたが、それは単にバイナリデータを出し入れするだけであり、バイナリデータを検索の対象にするものではなかった。
Lucene 2.9で追加されたIndexableBinaryStringToolsクラスを使うとバイナリデータ(byte[])をソートオーダーを維持したまま、インデックスに索引付けできるStringに変換できる。これにより、バイナリデータも検索できるようになった。もっともこのクラスが導入された動機は、ロケールに依存したトークンのソートを行うためにCollatorを使った場合、さらにソートの高速化のためにCollationKeyによって変換されたバイナリデータを索引付けしたいがためのものである。
関連JIRA:
IndexableBinaryStringToolsクラスの導入
https://issues.apache.org/jira/browse/LUCENE-1434
トークンをCollationKeyで変換、IndexableBinaryStringToolsでエンコードするCollationKeyFilterの導入
https://issues.apache.org/jira/browse/LUCENE-1435
Lucene 2.9ではCollationKeyFilterはcontrib/collationの下にJDKのCollatorを使った実装と、ICUのものを使った実装が同居していたが、現在開発中のLucene 3.1ではJDKのものをLucene coreに移動し、ICUライブラリに依存する実装はcontrib/icuというディレクトリが新設されてそこに移動された。これにともない、contrib/collationディレクトリは廃止された:
https://issues.apache.org/jira/browse/LUCENE-2124
このような背景のIndexableBinaryStringToolsではあるが、あえてバイナリデータを登録(索引付け)し、検索してみると、次のようなプログラムになる:
public class TestIndexableBinaryStringTools {
static Directory dir = new RAMDirectory();
static Analyzer analyzer = new WhitespaceAnalyzer();
public static void main(String[] args) throws IOException {
makeIndex();
searchIndex();
}
static void makeIndex() throws IOException {
IndexWriter writer = new IndexWriter( dir, analyzer, true, MaxFieldLength.LIMITED );
for( int i = 0; i < 3; i++ ){
Document doc = new Document();
doc.add( new Field( "id", Integer.toString( i ), Store.YES, Index.ANALYZED ) );
doc.add( new Field( "data", bytes2String( new byte[]{ (byte)i } ), Store.YES, Index.NOT_ANALYZED ) );
writer.addDocument( doc );
}
writer.close();
}
static String bytes2String( byte[] data ){
CharBuffer charBuffer = IndexableBinaryStringTools.encode( ByteBuffer.wrap( data ) );
return new String( charBuffer.array() );
}
static void searchIndex() throws IOException {
IndexSearcher searcher = new IndexSearcher( dir );
Query query = new TermQuery( new Term( "data", bytes2String( new byte[]{ 2 }) ) );
TopDocs docs = searcher.search( query, 10 );
for( ScoreDoc scoreDoc : docs.scoreDocs ){
Document doc = searcher.doc( scoreDoc.doc );
System.out.println( "id = " + doc.get( "id" ) );
System.out.println( "data = " + string2Bytes( doc.get( "data" ) )[0] );
}
searcher.close();
}
static byte[] string2Bytes( String s ){
ByteBuffer byteBuffer = IndexableBinaryStringTools.decode( CharBuffer.wrap( s.toCharArray() ) );
return byteBuffer.array();
}
}