カスタムフィールドに緯度経度が登録されたエントリーを近い順で取得するWordPress用クエリを書いたのでメモ。
WordPress3.1とMySQLの組み合わせで試した。
2点間の距離の計算には半正矢公式を使用している。
半正矢公式は通常、球面上にある 2 組の座標間の大圏距離を計算するのに使用されます。
詳しくはこちら↓
PHP、MySQL、Google マップを使用した店舗検索機能の作成
MySQL を使用して近くの場所を検索
http://code.google.com/intl/ja/apis/maps/articles/phpsqlsearch.html
前提としては、緯度経度をそれぞれlat, lngという名前で分けてカスタムフィールドに登録している。
lat, lngはpostmetaテーブルに保存されているが、同一レコードに記録されるのではなく
meta_keyフィールドにlat, lngがそれぞれ記録され、meta_valueフィールドに値が記録される。
というように2つのレコードに分かれているのが厄介。
下記クエリは重複してしまっているようなところがあるがひとまず動くことを優先にしている。
$lat, $lngには中心にしたい緯度経度を入力する。
50km以内で近い順に20件表示する設定になっている。
同じことをサブクエリを使わないで出来るWordPressの関数を使った方法がありそう。
$lat = 緯度;
$lng = 経度;
$posts = $wpdb->get_results(”
SELECT lat.lat\_id, lat.lat, lat.post\_title, lng.lng_id, lng.lng, (6371 \* acos(cos(radians($lat)) \* cos(radians(lat.lat)) \* cos(radians(lng.lng) – radians($lng)) + sin(radians($lat)) \* sin(radians(lat.lat)))) AS distance
FROM (SELECT DISTINCT id as lat\_id, meta\_value as lat, post_title FROM $wpdb->posts
JOIN $wpdb->postmeta ON ($wpdb->posts.ID = $wpdb->postmeta.post_id)
WHERE post\_type = ‘post’ AND post\_status=’publish’ AND meta_key = ‘lat’) as lat,
(SELECT DISTINCT id as lng\_id, meta\_value as lng FROM $wpdb->posts
JOIN $wpdb->postmeta ON ($wpdb->posts.ID = $wpdb->postmeta.post_id)
WHERE post\_type = ‘post’ AND post\_status=’publish’ AND meta_key = ‘lng’) as lng
HAVING lat.lat\_id = lng.lng\_id AND distance < 50 ORDER BY distance LIMIT 0 , 20; ");