検索条件が複雑になりがちなファセット検索ではJSON APIが威力を発揮します。
以下は、大阪市の施設情報のデータを使った区のフィールドによるファセット検索の例です。
$ curl -s http://localhost:8983/solr/test/query?omitHeader=yes -d '{
"query" : "*:*",
"offset" : 0,
"limit" : 0,
"facet" : {
"areas" : {
"type" : "terms",
"field" : "area",
"limit" : 3
}
}
}' |jq .
{
"response": {
"numFound": 9238,
"start": 0,
"docs": []
},
"facets": {
"count": 9238,
"areas": {
"buckets": [
{
"val": "平野区",
"count": 610
},
{
"val": "北区",
"count": 566
},
{
"val": "中央区",
"count": 509
}
]
}
}
}
複数のクエリによるファセット検索もすっきりと書けます。
以下は、大阪市役所の直線距離(0m~300m, 300m~500m, 500m~1km)で作成したファセットです。
$ cat request.json
{
query: "*:*",
offset: 0,
limit: 0,
facet: {
"300m": {
type: "query",
q: "{!frange l=0 u=0.3}geodist()",
},
"500m": {
type: "query",
q: "{!frange l=0.3 u=0.5}geodist()"
},
"1km": {
type: "query",
q: "{!frange l=0.5 u=1}geodist()"
}
}
params: {
pt: "34.6938,135.502002777777", /* 大阪市役所 */
sfield: "address_p"
}
}
$ curl -s http://localhost:8983/solr/test1/query?omitHeader=yes -d @request.json
{
"response":{"numFound":9238,"start":0,"docs":[]
},
"facets":{
"count":9238,
"300m":{
"count":28},
"500m":{
"count":27},
"1km":{
"count":185}}}
ファセットのネストも書けます。
以下の例では、上の例で作ったファセットのサブファセットとして施設タイプを指定しています。
$ cat request.json
{
query: "*:*",
offset: 0,
limit: 0,
facet: {
"300m": {
type: "query",
q: "{!frange l=0 u=0.3}geodist()",
facet: {
average_distance: "avg(geodist())",
types: {
type: "terms",
field: "type",
limit: 3
}
}
},
"500m": {
type: "query",
q: "{!frange l=0.3 u=0.5}geodist()",
facet: {
average_distance: "avg(geodist())",
types: {
type: "terms",
field: "type",
limit: 3
}
}
},
"1km": {
type: "query",
q: "{!frange l=0.5 u=1}geodist()",
facet: {
average_distance: "avg(geodist())",
types: {
type: "terms",
field: "type",
limit: 3
}
}
}
}
params: {
pt: "34.6938,135.502002777777", /* 大阪市役所 */
sfield: "address_p"
}
}
$ curl -s http://localhost:8983/solr/test1/query?omitHeader=yes -d @request.json
{
"response":{"numFound":9238,"start":0,"docs":[]
},
"facets":{
"count":9238,
"300m":{
"count":28,
"average_distance":0.18667141635662304,
"types":{
"buckets":[{
"val":"駅・バス停",
"count":8},
{
"val":"文化・観光",
"count":5},
{
"val":"官公庁",
"count":4}]}},
"500m":{
"count":27,
"average_distance":0.39623014517757793,
"types":{
"buckets":[{
"val":"駐車場・駐輪場",
"count":12},
{
"val":"文化・観光",
"count":6},
{
"val":"官公庁",
"count":2}]}},
"1km":{
"count":185,
"average_distance":0.7759130600495204,
"types":{
"buckets":[{
"val":"駐車場・駐輪場",
"count":62},
{
"val":"駅・バス停",
"count":46},
{
"val":"文化・観光",
"count":24}]}}}}
JSON API は複雑な検索リクエストをプログラム的に生成する場合に非常に有効なので、活用していきたいところです。