web-dev-qa-db-fra.com

Est-il possible d'enrouler la recherche de géolocalisation autour de WP_Query?

Je voudrais juste ajouter que j'ai une solution de travail en place et qui fonctionne bien, mais je cherche des idées pour pouvoir le faire mieux ou plus propre si possible.

Nous avons des centaines de propriétés dans un type de publication personnalisé avec metakey/metavalue contenant les coordonnées de longitude et de latitude des propriétés.

Nous permettons à un visiteur de saisir un lieu et un rayon pour rechercher ces propriétés dans cette zone. Un peu comme un localisateur de magasin. Voici comment je le fais en ce moment:

// 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);

Cela retourne un tableau de tous les identifiants de publication qui se trouvent dans les paramètres de recherche des utilisateurs. J'ai ensuite collé ce tableau dans WP_Query pour afficher uniquement les publications portant l'ID ci-dessus à l'aide de post__in. Je peux aussi faire d’autres critères de recherche sur le WP_Query par la suite.

Dans la requête ci-dessus, je fais une vérification de rayon carré et je sais que cela pourrait être facilement fait dans WP_Query en utilisant meta_query. Mais là où je suis coincé, c'est la vérification du rayon de cercle. Y a-t-il un moyen que je puisse envelopper cela dans WP_Query?

En gros, ce que je veux, c’est essayer de faire tout cela en un, plutôt que de faire deux tas de requêtes.

5
Brady

Je dupliquerais les coordonnées des publications dans une table séparée (post_id, lat, lon), avec un index sur (lat, lon). Je doute que la base de données puisse utiliser un index efficace avec votre requête.

Une fois, j'ai écrit une réponse à une question similaire en utilisant cette approche.

2
Jan Fabry