Laravel 5.1: Eloquent关系hasmany,记录限制

4

我有一个关于Laravel 5.1的问题:Eloquent关系hasmany,限制记录。我有两个表:feeds和comments。请求是根据每个特定的feed获取5个feed和相应的评论。我目前正在使用以下查询:

public function getFeed($user_id){
    return Feed::whereUserId($user_id)->with(['comments'])->take(10)->get()->map(function ($feed) {
        $feed->comments = $feed->comments->take(5);
        return $feed;
    });
}

然而,它返回了所有评论。

我的想法是$feed->comments = $feed->comments->take(5);这行代码不起作用。我只想获得每个Feed的5条评论,你有什么建议吗?非常感谢任何评论和建议。谢谢!

7个回答

3
如果这是适用于所有情况的内容,您可以像这样调整Feed模型中的关系:
public function comments() {
    return $this->hasMany('App\Comment')->limit(5);
}

3
这样做是行不通的,因为它会限制整个查询,在你使用->with()方法时。结果就是你只能得到5条评论,而实际上你想要每个父级关系下的5条评论。 - Flame

3

我也遇到同样的问题已经一个月了。我希望优化查询,因为从100万条记录中加载所需数据需要近1.5秒。

我使用了 Eloquent ORM集合加载(Collection Load()) 方法。这将加载时间降至仅300毫秒。

在你的情况下,

return Feed::whereUserId($user_id)
    ->get()
    ->each(function ($feed) {
        $feed->load('comments')->take(5);
    })
});

3
我认为限制/获取应该在load函数参数内定义,就像这样:$feed->load(['comments' => function ($query) { $query->take(5); }]); - Priit
这会导致N+1查询问题。 - Usama

3

“迟做总比不做好”,我昨天也遇到了同样的问题,最终将整个关系数组设置在模型上。

所以在你的情况下,代码应该是这样的:

return Feed::whereUserId($user_id)->take(10)->get()->map(function($feed) {
         $feed->setRelation('comments', $feed->comments->take(5));
         return $feed;
});

1
$feed= Feed::whereUserId($userId)->with(['comments'])->get()->map(function ($query) {
            $query->setRelation('comments', $query->comments->take(10));
            return $query;
        });

4
请在您的代码中添加一些解释,这将有助于提问者理解。 - fgamess

0

take() eloquent方法只是在查询末尾添加了“limit”关键字。这种类型的查询更加复杂,不受原生eloquent支持。

幸运的是,有一个名为eloquent-eager-limit的附加包可以解决这个问题。为了让它起作用,请使用composer require staudenmeir/eloquent-eager-limit命令安装该包,并在父模型和子模型类中都加入use \Staudenmeir\EloquentEagerLimit\HasEagerLimit;代码行。


0
Feed::whereUserId($user_id)->with([
    'comments' => function($query) {
         // You should limit the comments by editing the
         // relationships query not the main query.
         $query->take(5);
    }
])->take(10)->get();

通过这种方式,您可以限制您想要的订阅计数和每个订阅的评论计数。


2
限制只返回翻译后的文本:这将限制FID而不是注释。 - Pol Lluis
1
不,这样会限制它们两个。 - Ozan Kurt
1
白名单不起作用,这段代码将限制Feed为10,并仅获取5条评论并与10个Feed共享。 - keroles Monsef

-1

可能出错的地方在这里

$feed->comments = $feed->comments->take(5);

应该改为

$feed->comments = $feed->comments->take(5)->get();

我建议您这样写

$feed->load(['comments' => function($query){ return $query->take(5); }])


take()是一个令人困惑的函数:它在查询实例中被映射为limit(),但在集合实例中调用时与查询无关。我建议只在处理集合实例时使用它。在这种情况下,您永远不需要调用->get(),因为在集合中这意味着不同的事情。 - Flame

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接