我正在使用“WP_GeoQuery”类,它扩展了WP_Query,因此我们可以通过英国邮政编码(lat和long坐标)搜索帖子。它工作得非常好,但速度非常慢。
使用以下代码扩展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)
}
答案 0 :(得分:0)
我无法找到扩展WP_Query类的解决方案,但我找到了另一种解决方案。
通过自定义页面调用搜索,调用新的WP_GeoQuery类而不是WP_Query。
只有2个帖子用于测试目的,但搜索过程非常缓慢。经过一些测试后,我设法确定了使进程变慢的代码。这是公众&#34; posts_fields&#34;从我的第一篇文章中的原始WP_GeoQuery类中的函数。这包含了Haversine公式。
我原本以为当我查询Google以获取邮政编码(英国)的纬度/长距离时,我可能会陷入困境。经过一些测试,甚至切换到postcodes.io API(顺便推荐),这肯定不是问题,它肯定在WordPress查询中并指向&#34; posts_fields&#34;功能
我继续研究一些插件,寻找进行纬度/经度搜索的替代方法。许多可用的Geo插件非常复杂,难以剖析和隔离代码,因此我可以在我的插件中使用它,并使用我自己的自定义主题和搜索结果页面。
我最终找到了一个插件来完成这项工作。它是一个小插件,允许我在我的主题中使用它的功能并解决问题,因为现在搜索速度很快。缺点是该插件似乎不再受支持,并且已经更新了2年。但它工作得很好。该插件是&#34; GEO数据存储&#34; - https://wordpress.org/plugins/geo-data-store/
所以我不再使用自定义查询类,而是在激活此插件时以下列方式使用WP_Query:
$sc_gds = new sc_GeoDataStore();
$ids = (array) $sc_gds->getPostIDsOfInRange( $post_type, $radius, $latitude, $longitude );
$args= array(
'post__in' => $ids,
'posts_per_page' => 10,
'post_status' => 'any',
'post_type' => $post_type
);
$new_query = new WP_Query($args);
所以插件&#34; getPostIDsOfInRange&#34;函数获取属于给定纬度和经度半径的所有帖子ID。然后我们将这些ID放在&#34; post__in&#34;我们实现了WP_Query的参数。它很棒。
不是我想要的方式,因为扩展的WP_Query类似乎是最好的方法,但这是我发现的最快的解决方案。
我希望这有助于某人。