-
Notifications
You must be signed in to change notification settings - Fork 28
Builder::chunk may consider previously set offset and limit #103
Comments
This has recently been tried, but has been shot down by Taylor as expected behavior.
|
Yep, I've found it back: laravel/framework#9681. It's not that recent… Funny how my code came close to arrilot's one. |
@vlakoff there are not many other ways :) I (and probably many others) still disagree with @taylorotwell in this case but he is the boss in the end |
I will look into it again.
|
Thanks :-) Just a few reminders:
|
Just want to offer a friendly +1 for changing this. I literally just wrote the same lines expecting the chunk method to iterate over my given limit and offset values. It works perfectly with "whereBetween". thanks |
I've worked on a revised version which seems to be quite good. Already posting it here, if you want to have a glance at it: public function chunk($count, callable $callback)
{
$offset = $this->getOffset() ?: 0; // method to be implemented
$remaining = $this->getLimit(); // same
do {
if (! is_null($remaining)) {
$limit = min($count, $remaining);
} else {
$limit = $count;
}
$results = $this->skip($offset)->take($limit)->get();
$countResults = $results->count();
if ($countResults == 0) {
break;
}
// On each chunk result set, we will pass them to the callback and then let the
// developer take care of everything within the callback, which allows us to
// keep the memory low for spinning through large result sets for working.
if (call_user_func($callback, $results) === false) {
return false;
}
$offset += $countResults;
if (! is_null($remaining)) {
$remaining -= $countResults;
if ($remaining == 0) {
break;
}
}
} while ($countResults == $limit);
return true;
} |
Calling Would it be worth it to backup/restore these properties, or is it acceptable to consider the instance is "dirty" once the queries have been run? edit: just submitted laravel/framework#16479 about this. |
Just chiming in with the need for this. Found this thread after writing limit()->chunk() logic and finding it not working. |
+1 Same issue here. Just came across a scenario expecting limit to work and am now trying to implement my own tick limit. It's isn't easy to break out because it's a closure passed to an internal loop, so Anyone got a better way to break out of it?
|
I've implemented a different approach: Builder::macro("chunkWithLimit", function ($count, $from, $to, callable $callback) {
$page = 1;
do {
$offset = ($page - 1) * $count + $from;
$results = $this->offset($offset)->limit($count)->get();
$countResults = count($results);
if ($countResults == 0) {
break;
}
if ($callback($results) === false) {
return false;
}
$page++;
} while ($countResults == $count && $offset < $to - $count);
return true;
}); Maybe this will be useful |
This approach is interesting, as using extra parameters instead of the offset/limit properties allows to simplify a bit the implementation. (note your implementation has a flaw, it doesn't support partial pages. For example
My snippet above should work fine, but the boring part is updating the tests (mock skip/take instead of forPage) and adding new tests. If someone wants to take care of this, be my guest. I would be very grateful for this. |
Regardless of whether the function should be adapted or not, I do believe the docs need to be clearer about this. Similar to many others, the expected behaviour would be for the function not to ignore any offset/limits. Just one extra sentence in the docs could've saved me some debugging. |
@DiederikvandenB I'm sure a PR to the docs with that one extra sentence will be happily considered if it clarifies something that's lacking sufficient detail. |
And it will not necessary be merged but you should give it a try |
Facing same issue |
If someone wants to PR a clean solution for this I would be open to considering it. |
Suffering this issue after writing an Elasticsearch queue indexer. Very very hard to debug. |
The new code I posted above (wow, 2016) does work, but as I said in a later comment (specifically, "mock skip/take instead of forPage"), the tedious part is the tests. I had given it a try, but it was getting incredibly verbose... and boring. Anyone willing to support? |
Currently, if one does this:
He might expect to retrieve only the records from 1000 to 1500, but that's not the case: the whole table is retrieved. This is particularly surprising because other clauses such as
where
would be taken into consideration.I have come with a first draft, not yet tested, and it still feels clumsy…
So,
The text was updated successfully, but these errors were encountered: