dongqishou7471 2015-02-23 16:29
浏览 69
已采纳

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

I'm trying to sort an Eloquent ORM call based on the result of a method defined in a related model. I'm using 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). I want the list sorted by hotness, which is not a field in the db (the result of a function).

In the \App\Counts model we have a method called hotness()

This method performs a calculation on an algorithm similar to the reddit algorithm [see below for details]

I have a an Eloquent ORM call:

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

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:

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.

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?

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

enter image description here

T is the time in seconds between when the post was made an the date of the first post on the website

x is the number of upvotes minus the number of downvotes

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

z is the absolute value of x and 1

  • 写回答

1条回答 默认 最新

  • dousou2897 2015-03-12 14:51
    关注

    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.

    This allows me to ->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.

    I settled on 15 minutes as this allows the hotness to be fresh enough for the purposes of this application.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 fesafe材料库问题
  • ¥35 beats蓝牙耳机怎么查看日志
  • ¥15 Fluent齿轮搅油
  • ¥15 八爪鱼爬数据为什么自己停了
  • ¥15 交替优化波束形成和ris反射角使保密速率最大化
  • ¥15 树莓派与pix飞控通信
  • ¥15 自动转发微信群信息到另外一个微信群
  • ¥15 outlook无法配置成功
  • ¥30 这是哪个作者做的宝宝起名网站
  • ¥60 版本过低apk如何修改可以兼容新的安卓系统