Solrで緯度経度検索をする場合にはSpatial Searchを使います
検索項目に位置情報のフィルタリングを追加することで、検索の可能性を広げることができます
Spatial Searchで必要な設定
- JTS(JTS Topology Suite)のインストール
- 緯度経度検索をするフィールドタイプを追加
- 追加したフィールドタイプのフィールドを定義
JTSはJavaのライブラリで、地理空間情報処理のためのジオメトリエンジンです
JTS(JTS Topology Suite)のインストール
位置情報検索をするためのライブラリをSolrのlibディレクトリに配置します
JTSをダウンロードして解凍します
$ http://sourceforge.net/projects/jts-topo-suite/files/latest/download
$ unzip jts-1.13.zip
drwxr-xr-x 2 user user 4096 12月 10 2012 bin
drwxr-xr-x 3 user user 4096 12月 11 2012 doc
drwxr-xr-x 5 user user 4096 12月 13 2012 jtsio
drwxr-xr-x 2 user user 4096 12月 13 2012 lib
drwxr-xr-x 3 user user 4096 12月 13 2012 src
drwxr-xr-x 8 user user 4096 2月 8 2010 testxml
以下の2ファイルを$SOLR_HOME/lib
にコピーします
$ cp lib/jts-1.13.jar /usr/local/tomcat/webapps/solr/WEB-INF/lib/
$ cp lib/jtsio-1.13.jar /usr/local/tomcat/webapps/solr/WEB-INF/lib/
緯度経度検索をするフィールドタイプを追加
位置情報検索用のフィールドタイプを追加します
<fieldType name="location_rpt" class="solr.SpatialRecursivePrefixTreeFieldType"
spatialContextFactory="com.spatial4j.core.context.jts.JtsSpatialContextFactory"
distErrPct="0.025"
maxDistErr="0.000009"
units="degrees" />
追加したフィールドタイプのフィールドを定義
緯度経度検索をするフィールドを、追加したフィールドタイプで定義します
<field name="prefecture" type="pint" indexed="false" stored="true" multiValued="false"/>
設定が完了したらTomcatを再起動してインデクシングします。
今回はMySQLのgeometry型で緯度経度を保持している想定で作ったため、DataImportHandlerでデータを取得する再には以下のように取り込める状態に変換しました
concat(CAST(X(TKL.point) AS CHAR),' ',CAST(Y(TKL.point) AS CHAR)) AS point
※緯度経度の間にスペースがはいる以下の書式で取り込めます
35.01423 135.748218
データとしてはテスト用に以下のものを用意しました
検索地点:
京都駅 = 緯度:34.985458 経度:135.757755
検索対象データ:
二条城 = 緯度:35.01423 経度:135.748218
金閣寺 = 緯度:35.03937 経度:135.729243
まずは京都駅から半径10km圏内ということで以下のクエリをなげてみたところ、金閣寺と二条城両方が該当しました
{!geofilt point=distance sfield=point pt=34.985458,135.757755 d=10
}
距離は以下のように2つとも10km以内なので、期待した結果が返ってきました
金閣寺 <-> 京都駅 約6.5km
二条城 <-> 京都駅 約3.3km
次は、半径4km以内で検索してみました
{!geofilt point=distance sfield=point pt=34.985458,135.757755 d=4
}
今度は6kmはなれた金閣寺が出てこなかったので、これも期待した結果です
二条城が3km離れているので、2kmで検索してみました
次は、半径4km以内で検索してみました
{!geofilt point=distance sfield=point pt=34.985458,135.757755 d=2
}
次は両方とも該当しないという結果となりました。
テストとしては上記のデータではまだ不十分ですが、とりあえず機能を実装するといところまでは以上です。