Причина, по которой ваш фактический результат отличается от ожидаемого результата, связана с тем, как Laravel разбивает ваш набор данных.
Laravel разбивает на страницы через ваш набор данных по одной странице за раз и пропускаетколлекция Post
моделей для вашего обратного вызова.
Поскольку вы удаляете записи в наборе, Laravel эффективно пропускает страницу данных на каждой итерации, поэтому вы теряете примерно половину данных, которые былив исходном запросе.
Возьмите следующий сценарий - есть 24 записей , которые вы хотите удалить в кусках по 10 :
Ожидаемый
+-------------+--------------------+---------------------------+
| Iteration | Eloquent query | Rows returned to callback |
+-------------+--------------------+---------------------------+
| Iteration 1 | OFFSET 0 LIMIT 10 | 10 |
| Iteration 2 | OFFSET 10 LIMIT 10 | 10 |
| Iteration 3 | OFFSET 20 LIMIT 10 | 4 |
+-------------+--------------------+---------------------------+
Фактический
+-------------+--------------------+----------------------------+
| Iteration | Eloquent query | Rows returned to callback |
+-------------+--------------------+----------------------------+
| Iteration 1 | OFFSET 0 LIMIT 10 | 10 | (« but these are deleted)
| Iteration 2 | OFFSET 10 LIMIT 10 | 4 |
| Iteration 3 | NONE | NONE |
+-------------+--------------------+----------------------------+
После 1-й итерации осталось только 14 записей, поэтому, когда Laravel получил страницу 2, оннайдено только 4 записи.
В результате было удалено 14 записей из 24, что выглядит немного случайным, но имеет смысл с точки зрения того, как Laravel обрабатывает данные.
Другое решениек проблеме горе* * * * * * * * * * При использовании курсора используйте для обработки вашего запроса курсор, при этом будет проходить по 1 записи из набора результатов БД за раз, что лучше для использования памяти.
Например,
// laravel job class
// ...
public function handle()
{
$posts_archive = PostArchive::find(1); // just for the purpose of testing ;)
$query = Post::where('arch_id', $posts_archive->id);
foreach ($query->cursor() as $post) {
$post->delete();
}
}
Примечание: другие решения здесь лучше, если вы хотите только удалить записи в БД.Если у вас есть какая-либо другая обработка, которая должна произойти, тогда использование курсора было бы лучшим вариантом.