我使用的是WP_GeoQuery類,它擴展了WP_Query,因此我們可以通過英國郵政編碼(經緯度和長度座標)搜索帖子。它工作得很好,但速度非常慢。如何在WordPress中加速GEO搜索
當使用下面的代碼擴展WP_Query以加速MySQL請求時,我可以採取哪些步驟?
class WP_GeoQuery extends WP_Query
{
private $_search_latitude = NULL;
private $_search_longitude = NULL;
private $_radius = NULL;
/**
* Constructor - adds necessary filters to extend Query hooks
*/
public function __construct($args = array())
{
// Extract Latitude
if(!empty($args['latitude'])) { $this->_search_latitude = $args['latitude']; }
// Extract Longitude
if(!empty($args['longitude'])) { $this->_search_longitude = $args['longitude']; }
// Extract Longitude
if(!empty($args['radius'])) { $this->_radius = $args['radius']; }
// unset lat/long
unset($args['latitude'], $args['longitude'], $args['radius']);
// Extract Post type
if(!empty($args['post_type'])) { $this->_post_type = $args['post_type']; }
add_filter('posts_fields', array($this, 'posts_fields'), 10, 2);
add_filter('posts_join', array($this, 'posts_join'), 10, 2);
add_filter('posts_where', array($this, 'posts_where'), 10, 2);
add_filter('posts_orderby', array($this, 'posts_orderby'), 10, 2);
add_filter('posts_distinct', array($this, 'posts_distinct'), 10, 2);
// Run query
parent::query($args);
// Remove filters so only WP_GeoQuery queries this way
remove_filter('posts_fields', array($this, 'posts_fields'));
remove_filter('posts_join', array($this, 'posts_join'));
remove_filter('posts_where', array($this, 'posts_where'));
remove_filter('posts_orderby', array($this, 'posts_orderby'));
remove_filter('posts_distinct', array($this, 'posts_distinct'));
} // END public function __construct($args = array())
/**
* Return only distinct results
*/
function posts_distinct()
{
return "DISTINCT";
} // END public function posts_distinct()
/**
* Selects the distance from a haversine formula
*/
public function posts_fields($fields)
{
global $wpdb;
if(!empty($this->_search_latitude) && !empty($this->_search_longitude))
{
$fields .= sprintf(", (3959 * acos(
cos(radians(%s)) *
cos(radians(latitude.meta_value)) *
cos(radians(longitude.meta_value) - radians(%s)) +
sin(radians(%s)) *
sin(radians(latitude.meta_value))
)) AS distance ", $this->_search_latitude, $this->_search_longitude, $this->_search_latitude);
}
$fields .= ", latitude.meta_value AS latitude ";
$fields .= ", longitude.meta_value AS longitude ";
$fields .= ", location.meta_value AS location ";
return $fields;
} // END public function posts_join($join, $query)
/**
* Makes joins as necessary in order to select lat/long metadata
*/
public function posts_join($join, $query)
{
global $wpdb;
$join .= " INNER JOIN {$wpdb->postmeta} AS latitude ON {$wpdb->posts}.ID = latitude.post_id ";
$join .= " INNER JOIN {$wpdb->postmeta} AS longitude ON {$wpdb->posts}.ID = longitude.post_id ";
$join .= " INNER JOIN {$wpdb->postmeta} AS location ON {$wpdb->posts}.ID = location.post_id ";
return $join;
} // END public function posts_join($join, $query)
/**
* Adds where clauses to compliment joins
*/
public function posts_where($where)
{
$where .= ' AND latitude.meta_key="postcode_lat" ';
$where .= ' AND longitude.meta_key="postcode_lng" ';
$where .= ' AND location.meta_key="individual_details_postcode" ';
if(!empty($this->_search_latitude) && !empty($this->_search_longitude) && !empty($this->_radius))
{
if(is_numeric($this->_radius))
{
$where .= sprintf(' HAVING distance <= %s ', $this->_radius);
}
}
return $where;
} // END public function posts_where($where)
/**
* Adds where clauses to compliment joins
*/
public function posts_orderby($orderby)
{
if(!empty($this->_search_latitude) && !empty($this->_search_longitude))
{
$orderby = " distance ASC, " . $orderby;
}
return $orderby;
} // END public function posts_orderby($orderby)
}
在WP安裝中post_meta中有多少帖子具有lat/long值?許多?數百?成千上萬? –
此刻只有兩篇文章。這目前正處於測試階段。雖然我有經驗的開發與WordPress的我的知識缺乏MySQl優化,我假設這是查詢的速度有問題。默認的WordPress搜索速度非常快,但只要我使用修改WP_Query的這個類,它將花費1分鐘來加載,即使只有兩個帖子需要查詢。 – Steven
我一直在想你的問題。奇怪的是,只有兩個經緯度的查詢需要這麼長時間。我不知道你是否可以在查詢運行時用phpmyadmin或其他MySQL客戶端*訪問你的MySQL實例,*用'SHOW FULL PROCESSLIST'檢索查詢文本,並在這裏發佈查詢文本。 –