Solrでアルファベット順にソートする
Solrの検索結果をアルファベット順で上手にソートすることができず
日本語で検索してもなかなか参考になるものがなかったのでまとめ。
参考
SOLR 4.0 alphabetical sorting trouble - Stack Overflow
背景
今回は例として、ex_name
フィールドでindexingされている
aaa
、AAA
、bbb
、BBB
の4つの文字列を使います。
アルファベット順にソートしたいので、求める結果は以下の通り。
(ascかdescの指定が必要ですが、今回は重要じゃないので割愛)
aaa AAA bbb BBB
ですが、単純にソートを指定すると以下のような結果になります。
AAA BBB aaa bbb
文字コードにして並べた結果
小文字のaより大文字のBが優先されたんでしょうか。
この躓きを回避するための記事です。
環境
Solr 4.6.1(たぶん)
解決法
Solrにソート用のフィールドを追加します。
まず、scheme.xmlでソートに使うフィールドのfieldTypeを設定。
<fieldType name="alphaOnlySort" class="solr.TextField" sortMissingLast="true" omitNorms="true"> <analyzer> <tokenizer class="solr.KeywordTokenizerFactory"/> <filter class="solr.LowerCaseFilterFactory"/> <filter class="solr.TrimFilterFactory"/> <filter class="solr.PatternReplaceFilterFactory" replace="all" replacement="" pattern="([^a-z])"/> </analyzer> </fieldType>
ザックリ中身を解説すると
<filter class="solr.LowerCaseFilterFactory"/>`
でフィールドに含まれる大文字をすべて小文字に変換し
<filter class="solr.TrimFilterFactory"/>
でフィールド内の値の前後に含まれる空白を除去し
<filter class="solr.PatternReplaceFilterFactory" replace="all" replacement="" pattern="([^a-z])"/>`
でアルファベットのa〜z以外のすべて文字列を置換(削除)しています。
要するに、フィールド間の比較をすべて小文字で行うためのフィールドを作るわけですね。
次にソート用のフィールドを追加します。
<field name="sort_ex_name" type="alphaOnlySort" indexed="true" stored="false" multiValued="false" />
最後に、ex_name
をsort_ex_name
にコピーして完了。
<copyField source="ex_name" dest="sort_ex_name" />
この際に前述の3つのフィルタが動作し、ソート用に値を書き換えるようです。
これを保存して再度データをインポートした後に
sort_ex_name
でsortをすると、求めていた結果にたどり着けます。
まとめ
結果的に泥臭い方法になっている気がするけど、これでいいんだろうか。
あと、アルファベット以外(数字や記号)が先頭のものをどう扱うか。
ちなみにalphaOnlySort
というフレーズが
- Solrとして定義された語なのか
- 暗黙の了解的に使われてる語なのか
がわからずに実装中は悶々としていたのですが、「Apache Solr入門」曰く
SolrコミュニティではStrFieldのような組み込みの非テキスト系フィールド型の名前は習慣によって決められた名前が広く使われており〜独自名称を付けるのはお勧めしません
ということだそうで。何でもいいけどこの方がいい、なのかな。
今回は場当たり的に実装してるので、これからもっと勉強します。