按纬度和经度发布查询

时间:2016-10-23 作者:Rafal

我正在努力通过坐标获取帖子查询。我有元字段map_latmap_lng 对于几乎所有的帖子类型。我正在尝试从一种自定义帖子类型(本例中为“海滩”)返回帖子:

function get_nearby_locations($lat, $long, $distance){
    global $wpdb;
    $nearbyLocations = $wpdb->get_results( 
    "SELECT DISTINCT    
        map_lat.post_id,
        map_lat.meta_key,
        map_lat.meta_value as locLat,
        map_lng.meta_value as locLong,
        ((ACOS(SIN($lat * PI() / 180) * SIN(map_lat.meta_value * PI() / 180) + COS($lat * PI() / 180) * COS(map_lat.meta_value * PI() / 180) * COS(($long - map_lng.meta_value) * PI() / 180)) * 180 / PI()) * 60 * 1.1515) AS distance,
        wp_posts.post_title
    FROM 
        wp_postmeta AS map_lat
        LEFT JOIN wp_postmeta as map_lng ON map_lat.post_id = map_lng.post_id
        INNER JOIN wp_posts ON wp_posts.ID = map_lat.post_id
    WHERE map_lat.meta_key = \'map_lat\' AND map_lng.meta_key = \'map_lng\'
    AND post_type=\'beaches\'
    HAVING distance < $distance
    ORDER BY distance ASC;"
    );

    if($nearbyLocations){
        return $nearbyLocations;
    }
}
我给它打电话:

$nearbyLocation = get_nearby_cities(get_post_meta($post->ID, \'map_lat\', true), get_post_meta($post->ID, \'map_lng\', true), 25);
但它没有返回我想要的。

2 个回复
最合适的回答,由SO网友:cowgill 整理而成

关你需要另一个INNER JOIN 应该使用$wpdb->prepare.

我还加入了一个更有效的哈弗森公式(source) 来计算半径。

如果使用公里数,则更改$earth_radius 至6371。

此外,一种很好的调试方法是回显sql并将其粘贴到phpMyAdmin(或您使用的任何db应用程序)中,然后在其中进行调整。

function get_nearby_locations( $lat, $lng, $distance ) {
    global $wpdb;

    // Radius of the earth 3959 miles or 6371 kilometers.
    $earth_radius = 3959;

    $sql = $wpdb->prepare( "
        SELECT DISTINCT
            p.ID,
            p.post_title,
            map_lat.meta_value as locLat,
            map_lng.meta_value as locLong,
            ( %d * acos(
            cos( radians( %s ) )
            * cos( radians( map_lat.meta_value ) )
            * cos( radians( map_lng.meta_value ) - radians( %s ) )
            + sin( radians( %s ) )
            * sin( radians( map_lat.meta_value ) )
            ) )
            AS distance
        FROM $wpdb->posts p
        INNER JOIN $wpdb->postmeta map_lat ON p.ID = map_lat.post_id
        INNER JOIN $wpdb->postmeta map_lng ON p.ID = map_lng.post_id
        WHERE 1 = 1
        AND p.post_type = \'beaches\'
        AND p.post_status = \'publish\'
        AND map_lat.meta_key = \'map_lat\'
        AND map_lng.meta_key = \'map_lng\'
        HAVING distance < %s
        ORDER BY distance ASC",
        $earth_radius,
        $lat,
        $lng,
        $lat,
        $distance
    );

    // Uncomment and paste into phpMyAdmin to debug.
    // echo $sql;

    $nearbyLocations = $wpdb->get_results( $sql );

    if ( $nearbyLocations ) {
        return $nearbyLocations;
    }
}

SO网友:Rafal

我设法做到了:

function get_nearby_locations( $lat, $long, $distance ) {
    global $wpdb;

    // Radius of the earth 3959 miles or 6371 kilometers.
    $earth_radius = 3959;

    $sql = $wpdb->prepare( "
            SELECT DISTINCT
                map_lat.post_id,
                p.post_title,
                map_lat.meta_value as locLat,
                map_lng.meta_value as locLong,

                 (
        6371 * ACOS(
          COS(RADIANS( %s )) * COS(RADIANS(map_lat.meta_value)) * COS(
            RADIANS(map_lng.meta_value) - RADIANS( %s )
          ) + SIN(RADIANS( %s )) * SIN(RADIANS(map_lat.meta_value))
        )
      ) AS distance
     FROM $wpdb->posts p
            INNER JOIN $wpdb->postmeta map_lat ON p.ID = map_lat.post_id
            INNER JOIN $wpdb->postmeta map_lng ON p.ID = map_lng.post_id
            WHERE 1 = 1
            AND p.post_type = \'beaches\'
            AND p.post_status = \'publish\'
            AND map_lat.meta_key = \'geo_lat\'
            AND map_lng.meta_key = \'geo_lng\'
            HAVING distance < %s
            ORDER BY distance ASC",
            $earth_radius,
            $lat,
            $lng,
            $lat,
            $radius
        );

        // Uncomment to echo, paste into phpMyAdmin, and debug.
        // echo $sql;

        $nearbyLocations = $wpdb->get_results( $sql );

        if ( $nearbyLocations ) {
            return $nearbyLocations;
        }
    }