【问题标题】:Laravel 5.5 - How to query notifications for follower with created_at timestamp?Laravel 5.5 - 如何使用 created_at 时间戳查询关注者的通知?
【发布时间】:2018-09-20 17:05:13
【问题描述】:

用户可以是追随者和/或领导者。这里 userA 和 userB(都是领导者)在不同的时间被 userC(跟随者)跟随(请参阅下面的 followers 表以获取 created_at 时间戳)。

为了说明问题,我先布局模板:

userX action (year) // template to understand issue below

userC followed userA (2016)
userA added postA/notification (2017)
userC should get notification in feed, since they followed userA a year BEFORE their post

userB added postB/notification (2018)
userC followed userB (2019)
userC should NOT get notification in feed, since they followed userB a year AFTER their post

为此,我尝试了这个查询,但它不能正常工作:

$user = App\User::find(3); // follower
$leaders = $user->leaders()
                ->with(['leaderNotifications'=>function($query){
              $query->where('notifications.created_at','>','followers.created_at');
                }])
                ->get();

我认为该问题与未正确查询 created_at 有关。这是在本地查看的确切设置:

1) 数据库表名/数据

users

followers

notifications

2) 模型

// User
<?php
namespace App;

use Illuminate\Notifications\Notifiable;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\DatabaseNotification;
use Illuminate\Notifications\DatabaseNotificationCollection;

class User extends Authenticatable {
    use Notifiable;

    // Pivot Table
    public function leaders() {
      return $this->belongsToMany('App\User', ‘followers’, 'follower_id', 'leader_id')
                  ->withPivot('created_at'); // need timestamp to compare against notification timestamp
    }

    public function leaderNotifications() {
        return $this->hasMany(DatabaseNotification::class, 'leader_id')
                    ->orderBy('created_at', 'desc');
    }
}

我正在尝试获取当前关注者userC 的正确通知,这意味着只有他们关注领导者之后的新通知,而不是领导者之前的旧通知当前用户紧随其后。 还值得注意的是,最终查询一次应该能够paginate-&gt;(20) 这些通知,因为它将用一百万行进行测试,因此我们需要确保它高效/可扩展并且可以分页。 对于这个问题,高效/可扩展的查询是什么?

【问题讨论】:

  • 尝试使用DB::raw('followers.created_at')
  • @Ben 你知道如何扩展查询吗?当我有 10k - 1m 行的关注者时,我似乎无法让下面的 Mehran Prs 查询工作并且 php 内存不足,因此它效率不高/不可扩展。我真的不需要领导者()信息(因为我在通知的数据中有它),甚至可能不需要雄辩,但不知道如何使用DB::raw 来做到这一点,其中追随者有 10k - 1m 领导者,并且 1 位领导者有 10k - 100 万个帖子(尝试分页 20)。

标签: laravel laravel-5 eloquent laravel-5.5 eager-loading


【解决方案1】:

这是我解决它的方法,以防它帮助别人:

$user = App\User::find(3); // follower
$leaders = DB::table('notifications')
             ->join('followers','followers.leader_id','=','notifications.leader_id')
             ->where('followers.follower_id', $user->id)
             ->whereRaw('notifications.created_at > followers.created_at')
             ->paginate(20);

无需急切加载或使其更加复杂。只需一个简单的DB 查询即可处理!

【讨论】:

    【解决方案2】:

    1) 对于 Laravel 中的原始查询,您应该使用 whereRaw

    2) 使用with() 时,Laravel 在两个查询中获取数据,首先 获取父查询的结果,然后使用结果获取 with() , 如果你想在with闭包中使用第一个查询的数据透视列,你可以 加入。

    试试这个:

    $user = App\User::find(3); // follower
    $leaders = $user
              ->leaders()
              ->with(['leaderNotifications'=>function($query) use ($user){
                  $query->whereRaw('notifications.created_at > followers.created_at')
                        ->join('followers','followers.leader_id','=','notifications.leader_id')
                        ->where('followers.follower_id',$user['id']);
                     }])
                ->get();
    

    【讨论】:

    • 不幸的是,这在 10,000 到 100 万行上不起作用/扩展。仅在少数行上。尝试让此查询有效地工作,并且在获取每页限制为 20 个的关注者的领导者通知时不会耗尽内存。
    • 是的,但我尽量不要更改您的查询模板!!
    • 感谢您的帮助,但我认为我的方法不正确,这只是我试图让它发挥作用,这似乎不会很好地扩展。我赞成您的回答,因为您在whereRaw 上帮助了我 :)
    猜你喜欢
    • 2018-09-08
    • 1970-01-01
    • 1970-01-01
    • 2014-12-23
    • 2019-01-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-28
    相关资源
    最近更新 更多