Did*_*olo 15 php laravel eloquent laravel-5
我对Laravel的ORM Eloquent chunk()方法有疑问.它错过了一些结果.这是一个测试查询:
$destinataires = Destinataire::where('statut', '<', 3)
->where('tokenized_at', '<', $date_active)
->chunk($this->chunk, function ($destinataires) {
foreach($destinataires as $destinataire) {
$this->i++;
}
}
echo $this->i;
Run Code Online (Sandbox Code Playgroud)
它给出124838结果.
但是:
$num_dest = Destinataire::where('statut', '<', 3)
->where('tokenized_at', '<', $date_active)
->count();
echo $num_dest;
Run Code Online (Sandbox Code Playgroud)
得到249676,所以只有TWICE作为第一个代码示例.
我的脚本应该编辑数据库中的所有匹配记录.如果我多次启动它,它每次只分发剩余记录的一半.
我尝试使用DB :: table()而不是Model.我试图添加 - > take(20000),但似乎没有考虑到.我用 - > toSql()回显了查询,并且eveything似乎没问题(当我添加 - > take()参数时添加了LIMIT子句).
有什么建议 ?
Mis*_*aGH 30
想象一下,您正在使用chunk方法删除所有记录.该表有2,000,000条记录,您将删除所有这些记录1000个块.
$query->orderBy('id')->chunk(1000, function ($items) {
foreach($items as $item) {
$item->delete();
}
});
Run Code Online (Sandbox Code Playgroud)
它将通过在查询中获取前1000条记录来删除前1000条记录,如下所示:
SELECT * FROM table ORDER BY id LIMIT 0,1000
Run Code Online (Sandbox Code Playgroud)
然后chunk方法的另一个查询是:
SELECT * FROM table ORDER BY id LIMIT 1000,2000
Run Code Online (Sandbox Code Playgroud)
我们的问题在于,我们删除1000条记录,然后从1000到2000获取结果.实际上我们缺少前1000条记录,这意味着我们不会在大块的第一步删除1000条记录!其他步骤的情况也是如此.在每个步骤中,我们将错过1000条记录,这就是我们在这些情况下没有获得最佳结果的原因.
我做了一个删除示例,因为这样我们就可以知道chunk方法的确切行为.
更新:
您可以chunkById()安全地使用删除.
在这里阅读更多:
http://laravel.at.jeffsbox.eu/laravel-5-eloquent-builder-chunk-chunkbyid https://laravel.com/api/5.4/Illuminate/Database/Eloquent/Builder.html#method_chunkById
use*_*906 26
快速回答:使用chunkById()代替chunk()。
在迭代记录时更新或删除记录时,对主键或外键的任何更改都可能影响块查询。这可能会导致结果中不包含记录。
可以在Laravel 文档中找到解释:
以下是解决方案示例:
DB::table('users')->where('active', false)
->chunkById(100, function ($users) {
foreach ($users as $user) {
DB::table('users')
->where('id', $user->id)
->update(['active' => true]);
}
});
Run Code Online (Sandbox Code Playgroud)
如果您在对结果进行分块时更新数据库记录,您的分块结果可能会以意想不到的方式发生变化。如果您计划在分块时更新检索到的记录,最好使用 chunkById 方法。此方法将根据记录的主键自动对结果进行分页。
(更新结束)
原答案:
我遇到了同样的问题 - 只有总结果的一半传递给了chunk()方法的回调函数。
这是有问题的代码:
Transaction::whereNull('processed')->chunk(100, function ($transactions) {
$transactions->each(function($transaction){
$transaction->process();
});
});
Run Code Online (Sandbox Code Playgroud)
我使用 Laravel 5.4 并设法解决了用cursor()方法替换chunk ()方法并相应地更改代码的问题:
foreach (Transaction::whereNull('processed')->cursor() as $transaction) {
$transaction->process();
}
Run Code Online (Sandbox Code Playgroud)
尽管答案不能解决问题本身,但它提供了一个有价值的解决方案。
对于任何想要解决这个问题的代码的人来说,你可以去:
while (Model::where('x', '>', 'y')->count() > 0)
{
Model::where('x', '>', 'y')->chunk(10, function ($models)
{
foreach ($models as $model)
{
$model->delete();
}
});
}
Run Code Online (Sandbox Code Playgroud)
问题在于删除/删除模型,同时分析总数.将它包含在while循环中确保你得到它们!此示例适用于删除模型,更改while条件以满足您的需求!