我有一个非常大的结果集要处理,所以我使用 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 >= $maxchunk() 将停止查询数据库。它会导致 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/

10-14 15:24