はじめに
前回の記事で、SQLで言うdistinctをSolrで実現する方法を採り上げましたが、実はSolrでは部分的にではありますがSQLをサポートしており、もっと直接的にdistinctを実現することができます。
SolrのSQLサポート
Solrでは/sqlハンドラでSQLによるリクエストを受け付けます。/sqlハンドラは暗黙の内に設定されているもので、利用者が特に設定をすることなく利用できます。
サポートしているのは SELECT のみです。以下の機能が使えます。
- WHERE 句で Solr の検索式が書ける
- ORDER BY句によるソート
- LIMIT句による件数の指定
- SELECT DISTINCT句
- GROUP BY句による集約
- HAVING句
SELECT DISTINCT
前回の記事の、スポーツ施設で対応できるスポーツの一覧を取得する例は以下のように書けます。
$ curl -s --data-urlencode 'stmt=SELECT sports, count(*) AS cnt FROM sportare GROUP BY sports LIMIT 10' http://localhost:8983/solr/sportare/sql { "result-set":{ "docs":[{ "sports":"", "cnt":1} ,{ "sports":"BMX", "cnt":5} ,{ "sports":"アイスホッケー", "cnt":48} ,{ "sports":"アメリカンフットボール", "cnt":32} ,{ "sports":"アルペンスキー", "cnt":1} ,{ "sports":"アーチェリー", "cnt":113} ,{ "sports":"インディアカ", "cnt":16} ,{ "sports":"インラインスケート", "cnt":10} ,{ "sports":"ウィンドサーフィン", "cnt":1} ,{ "sports":"エアロビクス", "cnt":262} ,{ "EOF":true, "RESPONSE_TIME":155}]}}
試行錯誤中に、以下の問題を見付けました。
- テーブル名(Solrではコレクション名)に’-‘が含まれているとSQLの文法エラーになる。これはコレクション名のエイリアスを設定すればなんとかなる。
- LIMITで取得件数は指定できるが、OFFSETが指定できない。OFFSETを指定しても文法エラーにはならないものの、機能はしていないようです。
$ curl -s --data-urlencode 'stmt=SELECT sports, count(*) AS cnt FROM sportare GROUP BY sports LIMIT 10 OFFSET 5' http://localhost:8983/solr/sportare/sql { "result-set":{ "docs":[{ "sports":"", "cnt":1} ,{ "sports":"BMX", "cnt":5} ,{ "sports":"アイスホッケー", "cnt":48} ,{ "sports":"アメリカンフットボール", "cnt":32} ,{ "sports":"アルペンスキー", "cnt":1} ,{ "sports":"アーチェリー", "cnt":113} ,{ "sports":"インディアカ", "cnt":16} ,{ "sports":"インラインスケート", "cnt":10} ,{ "sports":"ウィンドサーフィン", "cnt":1} ,{ "sports":"エアロビクス", "cnt":262} ,{ "EOF":true, "RESPONSE_TIME":168}]}}
おわりに
distinctつながりで、SolrのSQLサポートを調べてみました。distinctに限らず、制限事項がいろいろと存在するので使いどころが案外難しいという印象です。通常の検索処理でというよりもインデックスに対する統計処理などで使うのが良さそうです