Verwenden von database-Metawerten zum Berechnen einer neuen Post-Reihenfolge mit pre_get_posts oder einem ‘request’-Hook

UPDATE: Ich habe meine Implementierung der ausgewählten Antwort am Ende dieses Beitrags ausgearbeitet.

Ich implementiere einen Sortieralgorithmus, der auf Reddit Hotnessalgorithmus basiert, zusätzlich zu einem Time-Decay (wie Hacker News Hotness-Algorithmus ).

Der Code, mit dem ich zurzeit zufrieden bin, ist ein Ergebnis von Versuchen und Fehlern in einigen Excel-Tabellen und was nicht. Hier ist der Arbeitscode in PHP:

 ID, '_tjnz_hearts', true); $plays = get_post_meta($post->ID, '_tjnz_deals_plays', true); $downloads = get_post_meta($post->ID, '_tjnz_deals_downloads', true); $ups = get_post_meta($post->ID, '_tjnz_temperature_upvotes', true); $downs = get_post_meta($post->ID, '_tjnz_temperature_downvotes', true); $date = get_post_time('U', true); // fetches the GMT postdate of post in Unix format $score = ( ( $hearts * 2 ) + $plays + $downloads + $ups ) - $downs; $order = log( max( abs( $score ), 1 ), 6 ); $seconds = $date - 1211380200; if( $score > 0 ) { $sign = 1; } elseif( $score  

ID; ?>
<?php echo 'hearts: ' . $hearts . '
'; echo 'plays: ' .$plays . '
'; echo 'dls: ' .$downloads . '
'; echo 'up: ' .$ups . '
'; echo 'down: ' .$downs . '
'; echo 'date: ' .$date . '

'; echo 'score: ' .$score . '
'; echo 'order: ' .$order . '
'; echo 'seconds: ' .$seconds . '
'; echo 'timenow: ' .$timenow . '
'; echo 'difference: ' .($timenow - $seconds) . '
'; echo 'sign: ' .$sign . '

'; echo 'hotness: ' .$hotness . '
'; echo 'degrees: ' .$degrees; ?>


Das Problem

Das Problem mit diesem PHP-Code ist, dass die WordPress-Abfrage bereits erstellt wurde, so dass die Posts nur anti-chronologisch zurückgegeben werden.

  • Ich möchte Posts nach ‘Hotness’ Score sortieren
  • Ich möchte kein neues WP_Query-Objekt oder query_posts () verwenden, da dies die ursprüngliche Abfrage stampfen würde, was zu unnötigen databaseinteraktionen führt. Die Seite ist ziemlich beschäftigt und ich hosste jetzt über tausend Beiträge.
  • Ich bin mir nicht sicher, wie man pre_get_posts oder den request Hook benutzt. Ja, ich habe die Dokumentation gelesen, aber für mich wird es jetzt zu weit fortgeschritten.

Die databasestruktur

Ich spare wp_postmeta Werte in der Tabelle wp_postmeta , wie Sie aus meinem PHP-Code-Snippet sehen können. Der tatsächliche Hotness-Score wird während der Fahrt berechnet und nicht in der database gespeichert, da dies nicht sehr effizient und vor allem nicht für Benutzer in Echtzeit wäre.

Meine eigentliche Frage

Ich kann die Abfrage nicht nach meta_value , da Metawerte nur ein Teil der Gleichung sind. Ich möchte das Ergebnis der Gleichung als Sortierreihenfolge verwenden.

Wie ändere ich die WordPress-Hauptabfrage, um die meta_values ​​zu betrachten, die Hotness jedes Beitrags zu berechnen und diese Beiträge vom heißesten zum kältesten zurückzugeben?

Meine Umsetzung der gewählten Antwort

In functions.php ich die folgenden zwei functionen hinzugefügt.

 // add custom wp_postmeta when a new post is created add_action( 'wp_insert_post', 'tjnz_prepare_postmeta' ); function tjnz_prepare_postmeta( $post_id ) { if ( !wp_is_post_revision( $post_id ) ) { $hotness = round( ( time() - 1211380200 ) / 336000, 7 ); add_post_meta( $post_id, '_tjnz_hearts', 0, true ); add_post_meta( $post_id, '_tjnz_plays', 0, true ); add_post_meta( $post_id, '_tjnz_downloads', 0, true ); add_post_meta( $post_id, '_tjnz_upvotes', 0.000, true ); add_post_meta( $post_id, '_tjnz_downvotes', 0.000, true ); add_post_meta( $post_id, '_tjnz_hotness', $hotness, true ); } } // build an array of Hotness stats for post function tjnz_temperature( $tjnz_post_id, $tjnz_timenow ) { $hearts = get_post_meta($tjnz_post_id, '_tjnz_hearts', true); $plays = get_post_meta($tjnz_post_id, '_tjnz_plays', true); $downloads = get_post_meta($tjnz_post_id, '_tjnz_downloads', true); $ups = get_post_meta($tjnz_post_id, '_tjnz_upvotes', true); $downs = get_post_meta($tjnz_post_id, '_tjnz_downvotes', true); $hotness = get_post_meta($tjnz_post_id, '_tjnz_hotness', true); $date = get_post_time('U', true); $score = $hearts + $downloads + $ups - $downs; $log = log( max( abs( $score ), 1 ), 6 ); $seconds = $date - 1211380200; if( $score >= 0 ) { $sign = 1; } else { $sign = -1; } $degrees = round( ( $log * ( $sign * 32 ) ) + ( ( -9.6 * ( $tjnz_timenow - $seconds ) ) / 336000 ) + 10, 7 ); // round to 7 digits positive/negative -2.4 degrees/day realtime post age +10 free degrees return array( 'hearts' => $hearts, 'plays' => $plays, 'downloads' => $downloads, 'ups' => $ups, 'downs' => $downs, 'score' => $score, 'hotness' => $hotness, 'degrees' => $degrees ); } 

_tjnz_hotness ist jetzt ein Metawert für jeden veröffentlichten Beitrag und wird jedes Mal aktualisiert, wenn ein Nutzer Ups, Downvotes, Downloads oder Favoriten (Herzen) posten kann. Der Wert von _tjnz_hotness basiert zunächst auf der Veröffentlichungszeit (GMT) des _tjnz_hotness mit einer score von 0. Die Veröffentlichungszeit basiert auf dem Unix Epoch-Zeitstempel des Posts, abzüglich meiner persönlichen Epoche (dem Datum, an dem mein Blog veröffentlicht wurde). Es ist wirklich egal, was diese Zahl ist, es _tjnz_hotness nur den Wert von _tjnz_hotness . Ein Beitrag, der direkt nach dem Start meines Blogs veröffentlicht wird, hat einen Wert nahe 0.

_tjnz_degrees wird bei jedem Laden der Seite berechnet. Die Seite verwendet die function tjnz_temperature() , um den tjnz_temperature() zum Zeitpunkt des tjnz_temperature() der Seite zu berechnen. Er holt alle Meta-Informationen aus dem Post und berechnet daraus die aktuelle Temperatur des Posts.

Der Hauptunterschied zwischen hotness und degrees ist, dass die hotness für die eigentliche Sortierung des Pfostens verwendet wird. Das Erhöhen / Verringern dieses Werts versetzt den Post auf einer Timeline im Verhältnis zu anderen Posts im Grunde versetzt. Der degrees basiert auf diesem Wert, berücksichtigt jedoch das Echtzeitalter eines Posts.

Im Wesentlichen bedeutet dies, dass, wenn sich die hotness eines hotness nicht ändert, der hotness tatsächlich hotness (0,1 Grad pro Stunde, 2,4 pro Tag).

Die Einrichtung der log Base 6 macht es auch so, dass mehr und mehr Upvotes benötigt werden, um den Post “heiß” zu halten. Irgendwann wird es einen Punkt geben, wo es einfach nicht mehr von neueren Posts gewinnen kann. Mit meiner Formel dauert es etwa 5-7 Tage, bis ein Beitrag zwangsläufig “kalt” wird.

Auf meiner benutzerdefinierten Seite listet ich die Posts wie folgt auf (es ist eine Debug-Ausgabe, es wird noch kein tatsächlicher Post-Inhalt angezeigt).

  'publish', 'post_type' => 'post', 'meta_key' => '_tjnz_hotness', 'posts_per_page' => 30, 'orderby' => 'meta_value_num', 'order' => 'DESC' ) ); if ( $hot_query->have_posts() ) : while ( $hot_query->have_posts() ) : $hot_query->the_post(); $tjnz_temperature = tjnz_temperature( $post->ID, $timenow ); ?>  ID; ?>
<?php echo 'hearts: ' . $tjnz_temperature['hearts'] . '
'; echo 'plays: ' . $tjnz_temperature['plays'] . '
'; echo 'dls: ' . $tjnz_temperature['downloads'] . '
'; echo 'up: ' . $tjnz_temperature['ups'] . '
'; echo 'down: ' . $tjnz_temperature['downs'] . '
'; echo 'score: ' . $tjnz_temperature['score'] . '
'; echo 'hotness: ' . $tjnz_temperature['hotness'] . '
'; echo 'degrees: ' . $tjnz_temperature['degrees']; ?>

Oops, Post Not Found!

Solutions Collecting From Web of "Verwenden von database-Metawerten zum Berechnen einer neuen Post-Reihenfolge mit pre_get_posts oder einem ‘request’-Hook"

Neulich habe ich darüber nachgedacht, wie man so etwas macht, ich würde empfehlen, die Hotnets als Post-Meta-Wert zu speichern, der bei jeder Abstimmung aktualisiert, gespeichert oder aktualisiert wird, dafür benötigen Sie den save_posts-Filter und dann können Sie Holen Sie sich die bestellten Posts mit pre_get_posts und eine Meta-Abfrage so etwas wie

 $query->set('meta_key'=>'hottnes'); $query->set('orderby'=>'meta_value_num'); $query->set('order'=>'DESC'); 

Hoffe das hilft.