Query posts distinct authors

时间:2015-02-05 作者:CiprianD

我试图从一个随机排序的类别中获取帖子,但要确保作者不会重复自己。

因此,我提出了这个问题,它按预期工作,但作者有可能会在这4篇文章中重复。那么,有没有办法确保它不会发生?

我曾考虑使用$wpdb,但我希望有一个更直接的解决方案。

$args = array (
\'post_type\'              => \'post\',
\'post_status\'            => \'publish\',
\'category_name\'          => \'premium\',
\'orderby\'                => \'rand\',
\'posts_per_page\'         => 4,
\'post__not_in\'           => get_option( \'sticky_posts\' ),
\'date_query\'             => array(
    array(
         array(
                \'before\' => \'this week\'
        ) 
    ),
),
);
$query = new WP_Query( $args );
编辑:

我一直在循环中尝试这一点。但由于某些原因,只显示了一个post get,并且$temp数组中仍然填充了所有的副本。

$temp=array();

if ($query->have_posts()) : while ($query->have_posts()) : $query->the_post();

 $author_id = the_author_meta( \'ID\' );
 if( !in_array($author_id, $temp) ):
  array_push($temp, $author_id);
  //loop stuff
 endif;
endwhile;endif;wp_reset_query();

3 个回复
最合适的回答,由SO网友:Pieter Goosen 整理而成

根据您的要求,很难想出一些性能简单且可靠的方法。正如@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_cacheupdate_post_term_cache 实际上,完成查询所需的时间增加了一倍,而且整个过程中查询保持在20个。所以这不是一条路:-)

SO网友:birgire

出于好奇,我尝试了静态SQL查询,这一个似乎很有效:

SELECT r.post_author, r.ID, r.post_title FROM (
    SELECT  p.post_author, p.ID, p.post_title
    FROM wp_posts p 
    INNER JOIN wp_term_relationships tr ON ( p.ID = tr.object_id ) 
    WHERE    p.post_date < \'2015-02-05 00:00:00\'
         AND p.ID NOT IN (10,20) 
         AND tr.term_taxonomy_id IN (1)
         AND p.post_type = \'post\' 
         AND p.post_status = \'publish\' 
    ORDER BY RAND() 
) as r 
GROUP BY r.post_author
LIMIT 0,4
首先,我在post_author 字段和订货人RAND() 但是,未聚合的字段没有与之配合。

但这当然不是很灵活;-)

SO网友:CiprianD

解释了另一种接缝工作的解决方案:here

在查询之前添加筛选器:

function filter_authors($groupby) {
 global $wpdb;
 $groupby = " {$wpdb->posts}.post_author";
 return $groupby;
}

add_filter(\'posts_groupby\',\'filter_authors\');
之后不要忘记将其移除:

remove_filter(\'posts_groupby\',\'filter_authors\');
这个解决方案非常好地工作。

结束

相关推荐

Loop for sticky posts

我用过Justin Tadlock\'s 关于如何创建仅包含粘性帖子的循环的教程。代码大致如下所示:$sticky = get_option( \'sticky_posts\' ); rsort( $sticky ); $sticky = array_slice( $sticky, 0, 2 ); query_posts( array( \'post__in\' => $sticky, \'caller_get_posts\' => 1 ) ); 根据教程,我