From 8b0c288f4fd9a02c15692cf3221c7d370a690f5f Mon Sep 17 00:00:00 2001 From: Eric Peterson Date: Sat, 22 Aug 2026 06:24:46 -0600 Subject: [PATCH] Add entity-aware chunk queries Closes #52 --- models/QuickBuilder.cfc | 28 +++++++++++++++++++ .../specs/integration/BaseEntity/GetSpec.cfc | 27 ++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/models/QuickBuilder.cfc b/models/QuickBuilder.cfc index 3e0d798e..91f1a51f 100644 --- a/models/QuickBuilder.cfc +++ b/models/QuickBuilder.cfc @@ -1304,6 +1304,34 @@ component accessors="true" transientCache="false" { return true; } + /** + * Retrieves the configured query in chunks and passes hydrated entities to + * the callback. Returning false from the callback stops further retrieval. + * + * @max The maximum number of entities in each chunk. + * @callback The callback invoked for each entity collection. + * @options Any options to pass to `queryExecute`. Default: {}. + * + * @return quick.models.QuickBuilder + */ + public any function chunk( + required numeric max, + required callback, + struct options = {} + ) { + activateGlobalScopes(); + variables.qb.chunk( + arguments.max, + function( rows ) { + var entities = variables._asQuery ? arguments.rows : arguments.rows.map( variables.loadEntity ); + var collection = getEntity().newCollection( handleTransformations( eagerLoadRelations( entities ) ) ); + return callback( collection ); + }, + arguments.options + ); + return this; + } + /** * Returns a Pagination Collection of entities. * diff --git a/tests/specs/integration/BaseEntity/GetSpec.cfc b/tests/specs/integration/BaseEntity/GetSpec.cfc index 6d44af93..b7ecc6b7 100644 --- a/tests/specs/integration/BaseEntity/GetSpec.cfc +++ b/tests/specs/integration/BaseEntity/GetSpec.cfc @@ -180,6 +180,33 @@ component extends="tests.resources.ModuleIntegrationSpec" { expect( p.results[ p.results.len() ].getId() ).toBe( 45 ); } ); + it( "can retrieve entities in chunks", function() { + var chunks = []; + var query = getInstance( "User" ) + .orderBy( "id" ) + .chunk( 2, function( users ) { + chunks.append( { + "size" : users.len(), + "firstId" : users[ 1 ].getId(), + "quickEntity" : users[ 1 ].isQuickEntity + } ); + return chunks.len() < 2; + } ); + + expect( query.isQuickBuilder ).toBeTrue(); + expect( chunks ).toHaveLength( 2 ); + expect( chunks[ 1 ] ).toBe( { + "size" : 2, + "firstId" : 1, + "quickEntity" : true + } ); + expect( chunks[ 2 ] ).toBe( { + "size" : 2, + "firstId" : 3, + "quickEntity" : true + } ); + } ); + it( "can eager load and paginate a Quick query", function() { queryExecute( "TRUNCATE TABLE `a`" ); queryExecute( "TRUNCATE TABLE `b`" );