web-dev-qa-db-ja.com

地理的位置検索をWP_Queryで囲むことは可能ですか。

私は現在の実用的な解決策が整っていてうまく機能していることを付け加えたいと思いますが、私はそれをより良くすることができるか可能ならばもっときれいにできるという考えを探しています。

プロパティの経度と緯度の座標を保持するmetakey/metavalueを持つカスタム投稿タイプには何百ものプロパティがあります。

私達は訪問者がその地域のそれらの特性を捜すために場所と半径をタイプインすることを可能にします。店舗検索のようなもの。これが私が現在どのようにやっているかです:

// Work out square radius
if(!empty($_SESSION['s_property_radius'])) {$dist = $_SESSION['s_property_radius'];}else{$dist = 50;}
$orig_lat = $_SESSION['s_property_address_lat'];
$orig_lon = $_SESSION['s_property_address_lng'];
$lon1 = $orig_lon - $dist / abs( cos( deg2rad( $orig_lat ) ) * 69 );
$lon2 = $orig_lon + $dist / abs( cos( deg2rad( $orig_lat ) ) * 69 );
$lat1 = $orig_lat - ( $dist / 69 );
$lat2 = $orig_lat + ( $dist / 69 );

// Compile a map search query to get all property ID's.
$mapsearchquery = "
            SELECT `t`.`ID`
            , 3956 * 2 * ASIN( SQRT( POWER( SIN( ( ".$orig_lat." - CAST(`t`.`property_address_lat` AS DECIMAL(9,6)) ) * pi() / 180 / 2), 2 ) + COS( ".$orig_lat." * pi() / 180) * COS( CAST(`t`.`property_address_lat` AS DECIMAL(9,6)) * pi() / 180 ) * POWER( SIN( ( ".$orig_lon." - CAST(`t`.`property_address_lng` AS DECIMAL(9,6)) ) * pi() / 180 / 2 ), 2 ) ) ) AS `distance` 
            FROM (

            SELECT `$wpdb->posts`.`ID`
            , MAX(CASE WHEN `$wpdb->postmeta`.`meta_key` = 'chb_homes_for_sale_address_longitude' THEN `$wpdb->postmeta`.`meta_value` END ) AS `property_address_lng`
            , MAX(CASE WHEN `$wpdb->postmeta`.`meta_key` = 'chb_homes_for_sale_address_latitude' THEN `$wpdb->postmeta`.`meta_value` END ) AS `property_address_lat`
            FROM `$wpdb->posts` 
            LEFT JOIN `$wpdb->postmeta` ON ( `$wpdb->posts`.`ID` = `$wpdb->postmeta`.`post_id` ) 
            WHERE `$wpdb->posts`.`post_status` = 'publish' 
            AND `$wpdb->posts`.`post_type` = 'homes-for-sale' 
            GROUP BY `$wpdb->posts`.`ID` 
            HAVING CAST(`property_address_lng` AS DECIMAL(9,6)) BETWEEN '".$lon1."' AND '".$lon2."' AND CAST(`property_address_lat` AS DECIMAL(9,6)) BETWEEN '".$lat1."' AND '".$lat2."'

            ) AS `t`
            HAVING `distance` < ".$dist."
        ";

// Just get the ID's
$mapsearchresults = $wpdb->get_col($mapsearchquery);

これは、ユーザーの検索パラメーター内にあるすべての投稿IDの配列を返します。その配列をWP_Queryに貼り付けて、上記のIDを持つ投稿のみをpost__inで表示します。あとでWP_Queryで他の検索基準を設定することもできます。

上記のクエリで、私は平方半径チェックをします、そして、私はこれがmeta_queryを使っているWP_Queryで簡単にされることができるということを知っています。しかし、私が動けなくなるのは、円の半径のチェックです。これをWP_Queryでラップする方法はありますか?

基本的には、2つのクエリを実行するのではなく、これらすべてを1つにまとめようとしています。

5
Brady

投稿の座標は、(post_id, lat, lon)のインデックスを持つ別のテーブル(lat, lon)に複製します。すべての結合とキャストで、データベースがあなたのクエリで効率的なインデックスを使うことができるとは思えません。

私はかつて 同様の質問に対する答え このアプローチを使って書いた。

2
Jan Fabry