У меня проблема с методом LARARL ORL 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;
Он дает 124838 результатов.
Но :
$num_dest = Destinataire::where('statut', '<', 3) ->where('tokenized_at', '<', $date_active) ->count(); echo $num_dest;
дает 249676, поэтому просто ДВАЖДЫ как первый пример кода.
Мой скрипт должен редактировать все соответствующие записи в базе данных. Если я запускаю его несколько раз, он просто раздаёт половину оставшихся записей каждый раз.
Я попытался использовать DB :: table () вместо Модели. Я попытался добавить a>> take (20000), но, похоже, это не учитывается. Я повторил запрос с помощью -> toSql (), и eveything кажется прекрасным (предложение LIMIT добавляется, когда я добавляю параметр -> take ()).
Какие-либо предложения ?
Для тех, кто ищет немного кода, который решает это, здесь вы идете:
while (Model::where('x', '>', 'y')->count() > 0) { Model::where('x', '>', 'y')->chunk(10, function ($models) { foreach ($models as $model) { $model->delete(); } }); }
Проблема заключается в удалении / удалении модели, в то время как она отрывается от общей суммы. Включая его в цикл while, вы обязательно получите их все! Этот пример работает при удалении моделей, измените условия в соответствии с вашими потребностями!
У меня была та же проблема – только половина общих результатов была передана функции обратного вызова метода chunk () .
Вот код, который имел проблемы:
Transaction::whereNull('processed')->chunk(100, function ($transactions) { $transactions->each(function($transaction){ $transaction->process(); }); });
Я использовал Laravel 5.4 и сумел решить проблему, заменив метод chunk () на метод cursor () и изменив код соответственно:
foreach (Transaction::whereNull('processed')->cursor() as $transaction) { $transaction->process(); }
Несмотря на то, что ответ не касается самой проблемы, он обеспечивает ценное решение.
Представьте, что вы используете метод chunk для удаления всех записей. Таблица имеет 2 000 000 записей, и вы собираетесь удалить их все на 1000 кусков.
$query->orderBy('id')->chunk(1000, function ($items) { foreach($items as $item) { $item->delete(); } });
Он удалит первые 1000 записей, получив первые 1000 записей в таком запросе:
SELECT * FROM table ORDER BY id LIMIT 0,1000
И тогда другой запрос из метода chunk:
SELECT * FROM table ORDER BY id LIMIT 1000,2000
Наша проблема заключается в том, что мы удаляем 1000 записей, а затем получаем результаты от 1000 до 2000. На самом деле нам не хватает первых 1000 записей, и это означает, что мы не собираемся удалять 1000 записей на первом этапе куска! Этот сценарий будет таким же для других шагов. На каждом этапе мы собираемся пропустить 1000 записей, и именно по этой причине мы не получаем лучший результат в этих ситуациях.
Я сделал пример для удаления, потому что таким образом мы могли бы узнать точное поведение метода chunk.
Я не мог решить эту проблему, мне пришлось перестать использовать chunk ().
Вот что я сделал, чтобы использовать простой старый PDO. Остерегайтесь одной вещи: переменная $ row, заполненная PDO, является (obvisouly) не Eloquent Model, а вместо этого просто объектом stdClass.
$pdo = \DB::connection()->getPdo(); $query = "SELECT * FROM $myModelTable WHERE ...."; $stmt = $pdo->prepare($query); $stmt->execute(); while ($row = $stmt->fetchObject()) { // $row is stdClass instead of MyModel }
Надеюсь это поможет. Я с нетерпением жду некоторой информации о случайном странном поведении этого куска.