根据您的要求,很难想出一些性能简单且可靠的方法。正如@birgire已经指出的,他的解决方案并不可靠,但从测试来看,它似乎是在平均0.015s的情况下,以2 db的查询打卡速度最快的。
从@birgire和我在评论中的快速讨论到his answer, 我决定试着用Wordpress提供的东西来做。到目前为止,这是最可靠的方法,但确实要付出一定的代价,在大约0.05秒的平均时间内以20 db的查询量打卡。
真正的大问题是,由于对随机结果的请求,您无法使用任何类型的缓存,因此我不得不寻找其他方法来减少时间和db调用。
对于第一部分,我使用this solution 作者@birgire(他在评论中也提到),我们利用pre_user_query
要更改的SQL查询WP_User_Query
仅随机获得所需的作者数量。这段代码速度非常快。为了提高性能,我还设置了WP_User_Query
只需要获得作者ID,因为这就是我们所需要的。此部分以平均0.002s的2 db查询打卡。
要从每个作者那里获得一篇文章,我们需要WP_Query
对于每个,在您的案例中总共是4个。这是该功能相当昂贵的一面。真正减慢查询速度的因素是,我们需要随机顺序,并且我们正在执行tax_query
以及使用join子句的。
我可以加快这一部分的速度的唯一方法就是只获取帖子ID。总的来说,这比获取完整的帖子并显示它们要快,而不仅仅是获取帖子ID并运行另一个帖子WP_Query
之后运行额外的WP_Query
好了,说得够多了,下面是函数:(可能需要一些微调)
function wpse177162_random_author_posts($number = 4, $args = [])
{
function my_pre_user_query( $q )
{
$limit = preg_replace( \'/[^\\d]/\', \'\', $q->query_limit );
$from = \'WHERE 1=1\';
$to = sprintf( \'WHERE RAND()<(SELECT ((%d/COUNT(*))*10) FROM %susers)\',
$limit,
$GLOBALS[\'wpdb\']->prefix
);
$q->query_where = str_replace( $from, $to, $q->query_where );
$q->query_orderby = \' ORDER BY RAND() \';
// remove the hook
remove_action( current_filter() , __FUNCTION__ );
}
$user_query_args = [
\'who\' => \'authors\',
\'fields\' => \'ID\',
\'number\' => $number,
];
add_action( \'pre_user_query\', \'my_pre_user_query\' );
$user_query = new WP_User_Query($user_query_args);
remove_action( \'pre_user_query\', \'my_pre_user_query\' );
$users = $user_query->results;
$post_ids = \'\';
if ($users) {
foreach ($users as $user) {
$user_args = [
\'author\' => $user,
\'fields\' => \'ids\',
\'no_found_rows\' => true
];
$combined_args = wp_parse_args($args, $user_args);
$q = new WP_Query($combined_args);
$q_posts[] = $q->posts;
}
foreach ($q_posts as $q_post) {
foreach ($q_post as $v ) {
$post_ids[] = $v;
}
}
}
return (array) $post_ids;
}
关于函数的一些注释
第一个参数$number
是要获取的作者数量
第二个参数是$args
与使用的参数相同WP_Query
并直接输入WP_Query
作为查询参数。您可以以同样的方式使用它,但有一个例外,不要设置作者参数,这将破坏函数
要了解如何使用它,您可以在模板中使用它,如下所示
$author_posts = wpse177162_random_author_posts(4, array(\'posts_per_page\' => 1, \'cat\' => 1, \'orderby\' => \'rand\'));
$q = new WP_Query(array(\'post__in\' => $author_posts));
如前所述,额外费用的原因
WP_Query
是为了性能,因为这样做可以在测试中获得更好的数字
根据@birgire的建议编辑,我已经用no_found_rows
保存db调用。我的性能确实略有提高,在测试中,我节省了4个db调用,尽管时间基本保持不变。
update_post_meta_cache
和update_post_term_cache
实际上,完成查询所需的时间增加了一倍,而且整个过程中查询保持在20个。所以这不是一条路:-)