前回取り上げた Result Grouping は Facet と組み合わせることができます。大阪の施設情報の例で言うと、type フィールドでファセットを作り、それぞれに含まれる area フィールドのグループの件数を求め る、といったことができます。
ただし、分散検索においては同じグループに属するドキュメントは同じシャードに置かれなければならない、という制限があります。
特定の条件に当てはまるドキュメントを同じシャードに配置するためにはドキュメントIDに複合キーを指定します。具体的には以下のような形になります。
通常
{"id":"10","type":"官公庁","area":"住之江区","name":"軽自動車検査協会大阪主管事務所","address":"住之江区南港東3-4-62","address_p":"34.6164938333333,135.438210722222"}
areaフィールドの値が同じドキュメントを同じシャードに配置
{"id":"住之江区!10","type":"官公庁","area":"住之江区","name":"軽自動車検査協会大阪主管事務所","address":"住之江区南港東3-4-62","address_p":"34.6164938333333,135.438210722222"}
idの値を “areaの値!本来のid” とすることでareaの値が同じドキュメントが同じシャードでインデックスされます。
組み合わせを試す前に、 まずは type フィールドを使った通常の Facet 検索の結果です。
$ curl -s 'http://localhost:8983/solr/osaka_shisetsu2/select?q=*:*&rows=0&facet=on&facet.field=type_str'
{
"responseHeader":{
"zkConnected":true,
"status":0,
"QTime":2,
"params":{
"q":"*:*",
"facet.field":"type_str",
"rows":"0",
"facet":"on"}},
"response":{"numFound":9238,"start":0,"maxScore":1.0,"numFoundExact":true,"docs":[]
},
"facet_counts":{
"facet_queries":{},
"facet_fields":{
"type_str":[
"駅・バス停",2574,
"公園・スポーツ",1090,
"駐車場・駐輪場",1049,
"学校・保育所",1045,
"医療・福祉",840,
"会館・ホール",642,
"名所・旧跡",561,
"警察・消防",330,
"公衆トイレ",322,
"官公庁",301,
"文化・観光",290,
"その他",141,
"環境・リサイクル",53]},
"facet_ranges":{},
"facet_intervals":{},
"facet_heatmaps":{}}}
それぞれの件数は Facet 内のドキュメントの件数を示しています。
次にグループ検索と Facet 検索の組み合わせです。
$ curl -s 'http://localhost:8983/solr/osaka_shisetsu2/select?q=*:*&group=true&group.field=area_str&rows=0&group.facet=true&facet=on&facet.field=type_str'
{
"responseHeader":{
"zkConnected":true,
"status":0,
"QTime":4,
"params":{
"q":"*:*",
"facet.field":"type_str",
"group.facet":"true",
"rows":"0",
"facet":"on",
"group.field":"area_str",
"group":"true"}},
"grouped":{
"area_str":{
"matches":9238,
"groups":[]}},
"facet_counts":{
"facet_queries":{},
"facet_fields":{
"type_str":[
"公園・スポーツ",25,
"公衆トイレ",25,
"医療・福祉",25,
"名所・旧跡",25,
"学校・保育所",25,
"官公庁",25,
"文化・観光",25,
"駅・バス停",25,
"その他",24,
"会館・ホール",24,
"警察・消防",24,
"駐車場・駐輪場",24,
"環境・リサイクル",20]},
"facet_ranges":{},
"facet_intervals":{},
"facet_heatmaps":{}}}
それぞれの件数はグループ数(Facet に含まれるエリアの種類)です。公共の施設なのでほとんどのタイプはほとんどの区に存在している(大阪24区+「大阪市以外」というタイプがあるためほとんどのグループ数は25になっている)ためあまりおもしろい結果ではありませんが、通常の Facet 検索との違いは良く分かると思います。
ちなみに、ドキュメントルーティングの設定をせずに作ったインデックスでの同じクエリの結果は以下の通りです。
$ curl -s 'http://localhost:8983/solr/osaka_shisetsu2/select?q=*:*&group=true&group.field=area_str&rows=0&group.facet=true&facet=on&facet.field=type_str'
{
"responseHeader":{
"zkConnected":true,
"status":0,
"QTime":7,
"params":{
"q":"*:*",
"facet.field":"type_str",
"group.limit":"3",
"group.facet":"true",
"rows":"0",
"facet":"on",
"group.field":"area_str",
"group":"true"}},
"grouped":{
"area_str":{
"matches":9238,
"groups":[]}},
"facet_counts":{
"facet_queries":{},
"facet_fields":{
"type_str":[
"医療・福祉",50,
"学校・保育所",50,
"官公庁",50,
"駅・バス停",50,
"公衆トイレ",49,
"名所・旧跡",49,
"会館・ホール",48,
"公園・スポーツ",48,
"駐車場・駐輪場",48,
"警察・消防",47,
"文化・観光",46,
"その他",40,
"環境・リサイクル",29]},
"facet_ranges":{},
"facet_intervals":{},
"facet_heatmaps":{}}}
2つのシャードそれぞれでグループ化が実行されるため、重複が発生してグループの数が倍近くになってしまいます。これを防ぐために複合キーを用いたドキュメントルーティングが必要になる訳です。