UPDATE: I have worked out my implementation of the selected answer at the bottom of this post.
我正在实现一个基于
Reddit\'s hotness algorithm, 除了时间衰减(如
Hacker News hotness algorithm).
我目前满意的代码是在一些Excel工作表和诸如此类的工作表中反复尝试的结果。以下是PHP中的工作代码:
<?php get_header();
$timenow = time() - 1211380200; // this is my custom Epoch time, it translates to when my first WP post was made ?>
<?php
if ( have_posts() ) : while ( have_posts() ) : the_post();
$hearts = get_post_meta($post->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 < 0 ) { $sign = -1; } else { $sign = 0; }
$hotness = round( $order + ( ( $sign * $seconds ) / 336000 ), 7 );
$degrees = round( ( $order * ( $sign * 32 ) ) + ( ( -4 * ( $timenow - $seconds ) ) / 336000 ), 7 ); ?>
<p>
<?php the_title(); ?> <?php echo $post->ID; ?><br />
<?php echo \'hearts: \' . $hearts . \'<br />\';
echo \'plays: \' .$plays . \'<br />\';
echo \'dls: \' .$downloads . \'<br />\';
echo \'up: \' .$ups . \'<br />\';
echo \'down: \' .$downs . \'<br />\';
echo \'date: \' .$date . \'<br /><br />\';
echo \'score: \' .$score . \'<br />\';
echo \'order: \' .$order . \'<br />\';
echo \'seconds: \' .$seconds . \'<br />\';
echo \'timenow: \' .$timenow . \'<br />\';
echo \'difference: \' .($timenow - $seconds) . \'<br />\';
echo \'sign: \' .$sign . \'<br /><br />\';
echo \'hotness: \' .$hotness . \'<br />\';
echo \'degrees: \' .$degrees; ?><hr />
</p>
<?php endwhile; else: ?>
<p><?php _e(\'Sorry, no posts matched your criteria.\'); ?></p>
<?php endif; ?>
The problem
这段PHP代码的问题是,WordPress查询已经完成,所以它只是按反时间顺序返回帖子。
我想按“热度”得分对帖子进行排序,我不想使用新的WP\\u查询对象或Query\\u posts(),因为这会影响原始查询,从而导致不必要的数据库交互。该网站相当繁忙,我现在正在托管一千多篇帖子我不知道如何利用pre_get_posts
或使用request
钩是的,我已经阅读了文档,但对我来说,它现在太高级了
The database structure
我正在表中保存meta\\u值
wp_postmeta
, 正如您可以从我的PHP代码片段中看到的那样。实际的热度分数是动态计算的,而不是保存到数据库中,因为这样做效率不高,最重要的是,对用户来说不是实时的。
My actual question
我无法对查询进行排序
meta_value
, 因为meta\\u值只是等式的一部分。我想使用
result 作为排序顺序。
如何更改WordPress主查询以查看meta\\u值,计算每个帖子的热度,并将这些帖子从最热返回到最冷?
My implementation of the chosen answer
在里面functions.php
我添加了以下两个函数。
// 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
现在是每个已发布帖子的meta\\u值,并且将在用户每次对帖子进行上投票、下投票、下载或收藏夹(红心)时更新。的价值
_tjnz_hotness
最初基于帖子的发布时间(GMT),并带有
score
共0个。发布时间基于帖子的Unix Epoch时间戳,减去我的个人Epoch(我的博客发布的日期)。这个数字是多少并不重要,它只是让
_tjnz_hotness
值较低。在我的博客发布后立即发布的帖子的值将接近0。
_tjnz_degrees
在每次页面加载时计算。页面使用函数tjnz_temperature()
要计算degrees
加载页面时的值。它从帖子中获取所有元信息,并使用它计算帖子的当前温度。
两者之间的主要区别hotness
和degrees
, 是吗hotness
用于对邮件进行实际排序。增加/减少此值基本上会相对于其他帖子抵消时间线上的帖子。这个degrees
值基于此,但它考虑了帖子的实时时间。
本质上,这意味着如果一篇文章hotness
不会改变degrees
实际值开始下降(每小时0.1度,每天2.4度)。
设置log
基数6也使得需要越来越多的更新投票来保持帖子的“热门”。最终,它将无法再从更新的帖子中获胜。按照我的公式,一篇帖子要花5-7天的时间才能不可避免地变得“冷”。
在我的自定义页面上,我列出了如下帖子(这是一个调试输出,还没有显示实际的帖子内容)。
<?php
/*
Template Name: Hot
*/
get_header();
$timenow = time() - 1211380200;
$hot_query = new WP_Query(
array(
\'post_status\' => \'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 );
?>
<?php the_title(); ?> <?php echo $post->ID; ?><br />
<?php echo \'hearts: \' . $tjnz_temperature[\'hearts\'] . \'<br />\';
echo \'plays: \' . $tjnz_temperature[\'plays\'] . \'<br />\';
echo \'dls: \' . $tjnz_temperature[\'downloads\'] . \'<br />\';
echo \'up: \' . $tjnz_temperature[\'ups\'] . \'<br />\';
echo \'down: \' . $tjnz_temperature[\'downs\'] . \'<br />\';
echo \'score: \' . $tjnz_temperature[\'score\'] . \'<br />\';
echo \'hotness: \' . $tjnz_temperature[\'hotness\'] . \'<br />\';
echo \'degrees: \' . $tjnz_temperature[\'degrees\']; ?><hr />
<?php endwhile; else : ?>
<p>Oops, Post Not Found!</p>
<?php endif; get_footer(); ?>