2015-09-21 7 views
5

У меня проблема с методом LARvel 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; 

Это дает 124838 результатов.

Но:

$num_dest = Destinataire::where('statut', '<', 3) 
    ->where('tokenized_at', '<', $date_active) 
    ->count(); 
echo $num_dest; 

дает 249676, так что просто ДВАЖДЫ как первый пример кода.

Мой сценарий должен редактировать все соответствующие записи в базе данных. Если я запускаю его несколько раз, он просто раздаёт половину оставшихся записей каждый раз.

Я попытался использовать DB :: table() вместо Модели. Я попытался добавить -> take (20000), но он, похоже, не принимается во внимание. Я повторил запрос с помощью -> toSql(), и eveything кажется прекрасным (предложение LIMIT добавляется, когда я добавляю параметр -> take()).

Любые предложения?

+0

Что такое $ this-> chunk output? – Dibesjr

+0

Это целое число (т.е. 2000), я переименовал его в $ chunk_size, это не помогло. –

+0

Не могли бы вы видеть, что такое выход или значение этой переменной? – Dibesjr

ответ

0

Я не мог решить эту проблему, мне пришлось перестать использовать 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 
} 

Надеюсь, что это поможет. Я с нетерпением жду некоторой информации о случайном странном поведении этого куска.

5

Для тех, кто ищет немного кода, который решает эту проблему, здесь вы идете:

while (Model::where('x', '>', 'y')->count() > 0) 
{ 
    Model::where('x', '>', 'y')->chunk(10, function ($models) 
    { 
     foreach ($models as $model) 
     { 
      $model->delete(); 
     } 
    }); 
} 

Проблема заключается в удаление/удаление модели, а комков далеко в общей сложности. Включая его в цикл while, вы обязательно получите их все! Этот пример работает при удалении моделей, измените условие while в соответствии с вашими потребностями!

1

У меня была такая же проблема - только половина общего результата была передана функции обратного вызова метода ().

Вот код, который имел проблемы:

Transaction::whereNull('processed')->chunk(100, function ($transactions) { 
    $transactions->each(function($transaction){ 
     $transaction->process(); 
    }); 
}); 

Я использовал Laravel 5.4 и удалось решить проблему, заменяющего кусок() метод с курсором() метода и изменения кода соответственно:

foreach (Transaction::whereNull('processed')->cursor() as $transaction) { 
    $transaction->process(); 
} 

Несмотря на то, что ответ не касается самой проблемы, он обеспечивает ценное решение.

1

Представьте, что вы используете метод 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 

А затем другой запрос от метода чанки:

SELECT * FROM table ORDER BY id LIMIT 1000,2000 

Нашего проблема заключается в том, что мы удаляем 1000 записей, а затем получаем результаты от 1000 до 2000. На самом деле нам не хватает первых 1000 записей, а это означает, что мы не собираемся удалять 1000 записей на первом этапе c красавчик! Этот сценарий будет таким же для других шагов. На каждом этапе мы собираемся пропустить 1000 записей, и именно по этой причине мы не получаем лучший результат в этих ситуациях.

Я сделал пример для удаления, потому что таким образом мы могли узнать точное поведение метода chunk.

+1

Это * актуальный * ответ с объяснением, почему проблема возникла в первую очередь. Текущий принятый ответ от Дидье - это просто хакерское решение. – Sacha

Смежные вопросы