it-swarm.com.de

Abfrage veröffentlicht unterschiedliche Autoren

Ich versuche, Beiträge aus einer zufällig sortierten Kategorie zu erhalten, stelle jedoch sicher, dass sich der Autor nicht wiederholt.

Ich habe also diese Abfrage, die wie beabsichtigt funktioniert, aber es besteht die Möglichkeit, dass der Autor diese 4 Beiträge wiederholt. Irgendwelche Ideen, wie ich sicherstellen könnte, dass dies nicht der Fall ist?

Ich habe überlegt, $ wpdb zu verwenden, aber ich habe auf eine einfachere Lösung gehofft.

$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 );

bearbeiten:

Ich habe das in der Schleife versucht. Aber aus irgendeinem Grund wird nur ein Beitrag angezeigt und das $ temp-Array wird immer noch mit allen Duplikaten gefüllt.

$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
CiprianD

Mit dem, was Sie fragen, ist es wirklich schwierig, einen performanten und einfachen Weg zu finden, der auch zuverlässig ist. Wie @birgire bereits sagte, ist seine Lösung nicht zuverlässig, aber aus Tests geht hervor, dass sie mit 2-dB-Abfragen im Durchschnitt von etwa 0,015 Sekunden die schnellste ist.

Von einer kurzen Diskussion zwischen @birgire und mir in Kommentaren zu seiner Antwort habe ich beschlossen, es mit dem zu versuchen, was Wordpress anbietet. Dies ist bei weitem der zuverlässigste Weg, hat jedoch einen gewissen Preis, da bei Abfragen mit 20 dB ein Durchschnitt von etwa 0,05 Sekunden erreicht wird.

Das wirklich große Problem ist, dass Sie aufgrund der Anfrage nach zufälligen Ergebnissen keine Art von Cache verwenden können. Daher musste ich nach anderen Möglichkeiten suchen, um Zeit und Datenbankaufrufe zu reduzieren.

Im ersten Abschnitt verwendete ich diese Lösung von @birgire (auch von ihm in Kommentaren erwähnt), wobei wir pre_user_query verwenden, um die SQL-Abfrage von WP_User_Query so zu ändern, dass nur die Anzahl der zufällig benötigten Autoren ermittelt wird. Dieser Abschnitt des Codes ist sehr schnell. Um die Leistung zu steigern, habe ich auch den WP_User_Query so eingestellt, dass nur die Autoren-IDs abgerufen werden, da dies alles ist, was wir benötigen. In diesem Abschnitt werden Abfragen mit einer Geschwindigkeit von 2 dB im Durchschnitt von 0,002 Sekunden ausgeführt.

Um einen einzelnen Beitrag von jedem Autor zu erhalten, müssen wir für jeden einen einzelnen WP_Query erstellen, was in Ihrem Fall insgesamt 4 ergibt. Dies ist die ziemlich teure Seite der Funktion. Ein Faktor, der die Abfragen wirklich verlangsamt, ist die Tatsache, dass wir eine zufällige Reihenfolge benötigen und dass wir auch einen tax_query erstellen, der Join-Klauseln verwendet.

Die einzige Möglichkeit, diesen Abschnitt zu beschleunigen, bestand darin, nur die Post-IDs abzurufen. Insgesamt ging dies schneller, als die vollständigen Beiträge abzurufen und anzuzeigen, als nur die Beitrags-IDs zu übernehmen und anschließend einen weiteren WP_Query auszuführen. Ich habe 7 Abfragen weniger, die eine zusätzliche Instanz von WP_Query ausführen.

OK, genug geredet, hier ist die Funktion: ( Kann vielleicht eine Feinabstimmung verwenden )

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;

}

Nur ein paar Hinweise zur Funktion

  • Der erste Parameter $number ist die Anzahl der Autoren, die abgerufen werden sollen

  • Der zweite Parameter ist $args, der mit den von WP_Query verwendeten Parametern identisch ist und auch direkt als Abfrageargumente in WP_Query eingegeben wird. Sie können dies genauso verwenden, mit einer Ausnahme, wenn Sie die Autorenparameter nicht festlegen, da dies die Funktion beeinträchtigt

Um zu verstehen, wie es verwendet wird, würden Sie es dann in Ihrer Vorlage wie folgt verwenden

$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));

Wie bereits erwähnt, liegt der Grund für den zusätzlichen WP_Query in der Leistung, da dies zu besseren Testergebnissen führte

BEARBEITEN

Auf Empfehlung von @birgire habe ich den obigen Code mit no_found_rows aktualisiert, um bei DB-Aufrufen zu sparen. Ich habe eine leichte Leistungssteigerung bekommen, beim Test habe ich 4 db Anrufe gespart, obwohl die Zeit im Grunde gleich blieb.

update_post_meta_cache und update_post_term_cache haben die für die Ausführung der Abfragen benötigte Zeit tatsächlich verdoppelt, und die Abfragen blieben durchgehend bei 20. Also kein Weg zu gehen :-)

1
Pieter Goosen

Aus Neugier spielte ich mit statischen SQL-Abfragen herum und diese schienen zu funktionieren:

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

Zuerst habe ich versucht, eine direkte Gruppe für das Feld post_author zu erstellen und nach Rand() zu sortieren, aber dann spielten die nicht aggregierten Felder nicht mit.

Aber das ist natürlich nicht sehr flexibel ;-)

2
birgire

Eine andere Lösung, die funktioniert, wird erklärt: hier

Hinzufügen des Filters vor der Abfrage:

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

add_filter('posts_groupby','filter_authors');

Und nicht zu vergessen, es später zu entfernen:

remove_filter('posts_groupby','filter_authors');

Diese Lösung funktioniert sehr gut.

0
CiprianD