我有一个非常大的结果集要处理,所以我使用 chunk()
方法来减少作业的内存占用。但是,我只想处理一定数量的总结果,以防止作业运行时间过长。
目前我正在这样做,但这似乎不是一个优雅的解决方案:
$count = 0;
$max = 1000000;
$lists = Lists::whereReady(true);
$lists->chunk(1000, function (Collection $lists) use (&$count, $max) {
if ($count >= $max)
return;
foreach ($lists as $list) {
if ($count >= $max)
break;
$count++;
// ...do stuff
}
});
有没有更干净的方法来做到这一点?
最佳答案
就目前而言,我不相信。
有一些问题和拉取请求提交给块尊重先前设置的跳过/限制,但泰勒已经关闭它们作为块覆盖这些的预期行为。
目前在 laravel/internals 仓库中有一个 open issue,他说他会再看看,但我认为它在优先级列表中并不高。我怀疑这是他会做的事情,但现在可能更容易接受另一个拉取请求。
您的解决方案看起来不错,除了一件事。 chunk()
将最终读取您的整个表,除非您从关闭中返回 false
。目前,您只是返回 null
,因此即使您的“max”设置为 1000000,它仍会读取整个表。如果您从 return false
时关闭 $count >= $max
, chunk()
将停止查询数据库。它会导致 chunk()
本身返回 false,但是您的示例代码无论如何都不关心 chunk()
的返回,所以没关系。
另一个选项,假设您使用的是顺序 ID,则是获取结尾 id
,然后在分块查询中添加一个 where 子句,以获取 id
小于最大 id
的所有记录。所以,像这样:
$max = 1000000;
$maxId = Lists::whereReady(true)->skip($max)->take(1)->value('id');
$lists = Lists::whereReady(true)->where('id', '<', $maxId);
$lists->chunk(1000, function (Collection $lists) {
foreach ($lists as $list) {
// ...do stuff
}
});
代码稍微干净一点,但它仍然是一个黑客,并且需要一个额外的查询(以获取最大 id)。
关于laravel - 限制 Eloquent 块,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/39029449/