简体   繁体   English

根据相关模型中方法的结果对Eloquent ORM结果集进行排序

[英]Ordering an Eloquent ORM resultset based on the result of a method in a related model

I'm trying to sort an Eloquent ORM call based on the result of a method defined in a related model. 我正在尝试根据相关模型中定义的方法的结果对Eloquent ORM调用进行排序。 I'm using Laravel 5. 我正在使用Laravel 5。

I want a list of posts including the posts author , location , comments and counts (which is a count of views , upvotes and downvotes for a post). 我想要一个posts列表,包括帖子authorlocationcommentscounts (这是一个帖子的viewsupvotesdownvotes的计数)。 I want the list sorted by hotness , which is not a field in the db (the result of a function). 我希望列表按hotness排序,这不是db中的字段(函数的结果)。

In the \\App\\Counts model we have a method called hotness() \\App\\Counts模型中,我们有一个名为hotness()的方法

This method performs a calculation on an algorithm similar to the reddit algorithm [see below for details] 此方法对类似于reddit算法的算法执行计算[详见下文]

I have a an Eloquent ORM call: 我有一个雄辩的ORM电话:

$posts = \App\Post::with('author')
  ->with('location.city')
  ->with('comments')
  ->with('counts')
  ->paginate(20);

The \\App\\Counts model contains fields for upvotes , downvotes , views , and a few other variables that are used when calculating the hotness of the post. \\App\\Counts模型包含upvotesdownvotesviews以及计算帖子upvotes时使用的一些其他变量的字段。

I can add the hotness value to the array that comes back from the counts model when paginating (on the fly) by overriding the toArray() method in my model like this: 我可以通过在我的模型中覆盖toArray()方法,在分页(动态)时将hotness值添加到从counts模型返回的数组中,如下所示:

public function toArray()
{
    $array = parent::toArray();
    $array['hotness'] = $this->hotness();
    return $array;
}

While this is useful in its own right, I can't achieve my objective, which is to sort the ORM paginated result by each posts hotness rating. 虽然这本身就很有用,但我无法实现我的目标,即按每个帖子hotness等级对ORM分页结果进行排序。

Is there any way I can achieve this without having a cron go through all the posts and calculate the hotness for each post every x minutes? 有没有什么方法可以实现这一目标, 而不是让cron通过所有帖子并计算每x分钟每个帖子的hotness

I would ideally like to be able to just add 理想情况下,我希望能够添加

->orderBy('hotness')

or 要么

->orderBy('counts.hotness')

but I have a feeling this might not be possible. 但我有一种感觉,这可能是不可能的。

Any creative ideas around how to solve this? 关于如何解决这个问题的任何创意?


Hotness Algorithm for reference 热度算法供参考

在此输入图像描述

T is the time in seconds between when the post was made an the date of the first post on the website T是帖子发布到网站上第一篇帖子的日期之间的秒数

x is the number of upvotes minus the number of downvotes x是upvotes的数量减去downvotes的数量

y is -1 if x < 0 , 0 if x = 0 and 1 if x > 0 y-1,如果x < 0 ,0,如果x = 01,如果x > 0

z is the absolute value of x and 1 zx和1的绝对值

It seems that the functionality I'm looking for is not achievable. 似乎我正在寻找的功能是不可实现的。

I ended up persisting hotness to the counts table and update the value in the overriding toArray() method. 我最终坚持hotnesscounts表并更新覆盖toArray()方法中的值。

This allows me to ->orderBy('counts.hotness') 这允许我->orderBy('counts.hotness')

In order to mitigate overhead I use a cache key that expires after 15 minutes so that I'm not calculating the hotness each time the counts model is converted to an array. 为了减轻开销,我使用一个15分钟后过期的缓存密钥,这样每次将counts模型转换为数组时我都不会计算hotness

I settled on 15 minutes as this allows the hotness to be fresh enough for the purposes of this application. 我坚持了15分钟,因为这样可以使hotness足够新鲜,以满足本申请的需要。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM