TypeScript Advanced Data Operations
These patterns use the Node SQL runtime and the generated School Management fixture. The browser TFP client deliberately exposes a narrower transport profile.
Search page with rows and two facets
One Request can return matching entities plus independently named navigation sidecars:
const rows = await Q.schools()
.withNameContaining("Primary")
.selectSchoolTypeWith(
Q.schoolTypesWithMinimalFields().selectCode().selectName())
.selectPlatformWith(Q.platformsWithMinimalFields().selectName())
.facetBySchoolTypeAs(
"schoolTypes",
Q.schoolTypesWithMinimalFields()
.withCodeIn("PRIMARY", "SECONDARY")
.selectCode().selectName().countSchoolsAs("schoolCount"),
true,
)
.facetByPlatformAs(
"platforms",
Q.platformsWithMinimalFields().selectName().countSchoolsAs("schoolCount"),
false,
)
.orderByIdDescending()
.limit(50)
.comment("Search schools with dashboard facets")
.purpose("Render the authorized operations dashboard")
.executeForList(context);
const typeBuckets = rows.facet("schoolTypes");
const platformBuckets = rows.facet("platforms");
The first Facet keeps allowed zero-count SchoolTypes. The second returns only
Platform values represented by the current match set. Both remain separate
from the primary rows collection.
Deep graph and per-parent Top-N
Every relation level receives a typed child Request. The child limit is applied per Platform, not to the combined School result:
const platforms = await Q.platforms()
.selectName()
.selectSchoolListWith(
Q.schools()
.selectName()
.selectSchoolTypeWith(
Q.schoolTypesWithMinimalFields().selectCode().selectName())
.orderByStudentCapacityDescending()
.limit(3),
)
.comment("Load each platform and its three largest schools")
.purpose("Render the authorized platform capacity review")
.executeForList(context);
Keep this on the Node SQL profile and verify the provider trace contains the partition/window Top-N plan when qualifying a database.
Grouped and relation analytics
Grouped analytics return record-shaped rows. Relation analytics retain typed parents and add named, read-only metrics:
const distribution = await Q.schools()
.groupBySchoolType()
.countAs("schoolCount")
.sumStudentCapacityAs("capacityTotal")
.avgStudentCapacityAs("capacityAverage")
.comment("Aggregate school capacity by type")
.purpose("Build the authorized capacity report")
.executeForRows(context);
const cards = await Q.schoolTypesWithMinimalFields()
.selectCode().selectName()
.countSchoolsAs("schoolCount")
.sumStudentCapacityOfSchoolsAs("capacityTotal", Q.schools())
.comment("Calculate type-level school metrics")
.purpose("Render the authorized type cards")
.executeForList(context);
Do not update an entity through an aggregate alias. distribution records and
the named metrics on cards are projections of database calculations.
Audited read-modify-save
let school = await Q.schools()
.withIdIs(schoolId)
.selectPlatformWith(Q.platformsWithMinimalFields().selectName())
.selectSchoolTypeWith(Q.schoolTypesWithMinimalFields().selectCode())
.comment("Load the complete school for capacity approval")
.purpose("Apply an authorized capacity revision")
.executeForOne(context);
if (!school) throw new Error("school not found");
school.updateStudentCapacity(newCapacity);
school = await school.auditAs("Approve revised student capacity").save(context);
Load every Checker/Fix input and retain the returned entity so subsequent mutations use the authoritative optimistic version.