用户可以是关注者和/或领导者。在这里,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->(20)
这些通知,因为它将测试一百万行,因此我们需要确保它高效/可扩展并且可以分页。
对于这个问题,有效/可扩展的查询是什么?
答案 0 :(得分:2)
以下是我如何解决它,以防其他人:
$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
查询即可处理它!
答案 1 :(得分:1)
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();