manoelfilho's avatar

How to go about chunkByID method with UUID primary keys?

Hello! I am having problems trying do this type of query:

Entity::where('type', 'value')->chunk(100, function ($elements) {
			foreach($elements as $element){
						//some editions here
			}
});

The problem: I am trying to use chunk, chunkById, cursor and lazy methods. Everything returns one half part of content. When I use the method count I can find the correct number. I saw that chunkById is the most correct for it according to laravel documentation, but I think the problem here is the use of UUID as primary keys.

Did someone have a situation like this?

0 likes
6 replies
Tray2's avatar

I highly recommend using integers as the primary key id. It will be much more performant than using uuids.

1 like
manoelfilho's avatar

Thanks, Tray2 !

The project requires UUID as it has several elements created offline in two different phone apps. It is a large and complex system. Already in production for a long time.

The curious thing is that questions like this type works well:

Entity::where('type', 'value')->chunk(100, function ($elements) {
			foreach($elements as $element){
						$element->save();
			}
});

Thank you very much for your comment

Tray2's avatar

@manoelfilho

If you are filtering the results of the chunk method based on a column that you will also be updating while iterating over the results, you should use the chunkById method. Using the chunk method in these scenarios could lead to unexpected and inconsistent results. Internally, the chunkById method will always retrieve models with an id column greater than the last model in the previous chunk:

https://laravel.com/docs/10.x/eloquent#chunking-results

manoelfilho's avatar

@Tray2 Sure. I was reading it. I think the problem is really about the use of UUID. There is a good explanation here: stackoverflow.com/questions/32700537/eloquent-chunk-missing-half-the-results

manoelfilho's avatar
manoelfilho
OP
Best Answer
Level 1

Good. I've been researching and I realized that chunkById is the most suitable method when we need to remove or update the models that we're going to go through with foreach. The chunkById problem in my case is the use of the UUID as the primary key. This type of key does not allow for proper searching. In this scenario, the most appropriate thing is to make an initial count of how many elements match your criteria in the query and use this value for a loop where each iteration takes the first occurrence of the element and then does what it needs.

function exampleWithoutChunk(){
	
	$collectionsCount = Entity::where('conditions here ...')
		->with('joins here ...')
		->count();

	for($i=0;$i < $collectionsCount; $i++){
		$myEntity = Entity::where('conditions here ...')
			->with('joins here ...')
			->get()
			->first();
		$myEntity->method();
	}

}

It is obvious that if you have a lot of elements, it will use a lot of processing. In my case, we use the process in queues.

eggplantSword's avatar

Late to the party. I was using chunkById and I fixed it by changing chunkById to chunk and adding orberBy('id') before the chunk in my query. In my case id is a uuid as well.

Please or to participate in this conversation.