我在排序/排序结果时遇到问题。 基本上我有帖子表,我根据有多少评论和喜欢来计算 popular_count 。问题是我也对结果进行了分页。所以 当我使用这样的东西时
$Posts->paginate(5);
$Posts->sortBy('popularity_count');
$Posts->get();
它仅针对特定页面进行排序,例如。第1页的结果与人气统计数字如:6,5,4,3,2,第二页有10,7,5,2,1。正如您所看到的,有人气 10 的帖子应该是第一页上的第一个结果。
当我尝试使用
时 $Posts->orderBy('popularity_count')
它不起作用,因为我的数据库中没有这样的列。有没有可能在不使用RAW选择和加入的情况下实现我想要的东西?我的模型上有更多自定义属性。
谢谢!
编辑:
`public function getPopularityCountAttribute(){
$comments = $this->getRelation('commentsCount');
$likes = $this->getRelation('likesCount');
$comments = ($comments) ? (int) $comments->comments_count : 0;
$likes = ($likes) ? (int) $likes->likes_count : 0;
$Result = $likes + ( $comments * 1.2 );
return $Result;
}`
答案 0 :(得分:3)
快速解决方案(在实施方面)是使用oderByRaw()
:
$Posts->orderByRaw("
(
select count(*)
from likes
where likes.post_id = posts.id
) + (
select count(*)
from comments
where comments.post_id = posts.id
) * 1.2 DESC
");
如果您的posts
表格很大,那么这将非常慢。您可以尝试使用两个连接和两个聚合创建查询,但这不会有太大变化。您想要仅获取5行并不重要 - 您需要计算"流行度"每次在DB中的每个帖子。
因此,如果性能问题,您可以创建三个新的"缓存" posts
表中的列:
likes_count
comments_count
popularity
包含popularity
列的索引。
每次插入或删除评论等时,您还需要更新相关帖子。我可能会用触发器做到这一点。
有了这个,你可以使用orderBy('popularity', 'DESC')
。
您还可以使用列post_popularity
创建一个新表(post_id, comments_count, likes_count, popularity
),以便将缓存的数据分开。但是你需要加入:
$Posts->join('post_popularity as pp', 'pp.post.id', '=', 'posts.id')
->orderBy(pp.popularity, 'DESC');
答案 1 :(得分:0)
您应该在获取数据之前对数据进行排序:
$Posts->orderBy('popularity_count')->paginate(5);
在sortBy()
之后使用paginate()
时,您只会对5个项目的集合进行排序。