Skip to main content

Query, Mutation, Analytics, and Facets

This is the common entry point for application data operations in TeaQL. Start here to choose the operation shape, then open the language page for exact generated syntax.

Business questionTeaQL operationResult shape
Which objects match?Typed Query with predicates, projection, relation selection, order, and paginationSmartList<Entity> or one typed entity
What are the totals?Aggregate-only QueryNamed aggregate metadata/result values
How are rows distributed?Group by plus named aggregatesOne result row per group
What statistics belong to each parent?Relation count/statisticNamed values attached to each parent row
Which filter choices and counts should the UI show?One or more relation FacetsNamed SmartList<Record> sidecars on the main SmartList
How do I create, update, or delete?Generated Mutation methods plus audited graph saveAuthoritative saved entity and version

Query: select the business rows​

A Query starts from generated Q, composes only modeled fields and relations, declares non-empty comment and purpose, and executes with trusted context.

Q.<entities>()
-> typed predicates
-> projection and relation selection
-> deterministic order and bound
-> comment + purpose
-> execute with context

The two intent calls may appear in either order and need not be adjacent. They describe the operation; they do not grant authorization. Tenant, actor, permission, provider, and safety limits come from context.

See the cross-language Query contract for predicate, relation, pagination, and evidence details.

Aggregation: calculate over one filtered population​

TeaQL has three related analytics shapes:

  1. Aggregate-only: count, sum, avg, min, or max over the complete filtered population.
  2. Grouped aggregate: add one or more generated groupBy... calls, then named aggregate aliases. Each group produces a result row.
  3. Relation aggregate: decorate every parent with a count or statistic over a typed, optionally filtered child Request.

Aliases such as schoolCount and capacityTotal are part of the result contract. They are analytic values, not modeled writable fields. Keep filters inside the request being aggregated; do not load all entities and recalculate database totals in application memory.

The portable seven-runtime aggregate family is:

FunctionTypical generated spelling
CountcountAs("schoolCount")
SumsumStudentCapacityAs("capacityTotal")
AverageavgStudentCapacityAs("capacityAverage")
MinimumminStudentCapacityAs("capacityMinimum")
MaximummaxStudentCapacityAs("capacityMaximum")

Casing follows the target language. Some runtimes expose additional functions, but variance, deviation, and bitwise aggregates are not part of the portable seven-language baseline.

Facet: return navigation buckets beside the rows​

A Facet is not just a group-by. It combines two Requests:

outer School request
filter: name contains "Primary"
main result: matching School rows

facet "schoolTypes" on School.schoolType
nested SchoolType request
projection: code
metric: count matching Schools as "schoolCount"
result: named bucket list attached to the outer SmartList

The nested Request decides which bucket fields and metrics are returned. The outer Request decides the active business population. Multiple Facets can be attached to one outer Request under different names.

Facet syntax variants​

VariantRequest shapeEffect
Default include-allfacetByRelationAs(name, child)All allowed child values; count metrics may be zero
Explicit include-allfacetByRelationAs(name, child, true)Same semantics, useful when the choice should be visible in code
Matched-onlyfacetByRelationAs(name, child, false)Remove buckets absent from the filtered outer population
Restricted bucket domainPut a typed predicate such as withCodeIn(...) on childConsider only the allowed subset of relation values
Rich bucket projectionAdd selectCode, selectName, or other generated selections to childReturn display-ready bucket fields
Multiple metricsAdd count...As, sum...As, or other relation statistics to childReturn several named values per bucket
Multiple FacetsChain two or more differently named facetBy...As callsReturn independent filter panels beside the same main rows

The child predicate and the include-all flag solve different problems. A child predicate defines which bucket values are allowed at all. Include-all decides whether allowed-but-unmatched values remain visible with zero counts.

Include-all versus matched-only​

OptionMeaningExample use
includeAllFacets = true (default)Return every allowed relation value; unmatched buckets carry zero for count metricsStable filter panels that must keep disabled/zero-count choices visible
includeAllFacets = falseReturn only relation values present in the filtered outer populationCompact drill-down lists and search suggestions

For a Primary school filter, include-all might return PRIMARY: 1 and SECONDARY: 0; matched-only returns only PRIMARY: 1. The Facet result is read by the name supplied at construction time:

LanguageConstruct a SchoolType facetRead it from the result
JavafacetBySchoolTypeAs("types", child, true)rows.getFacet("types")
Rustfacet_by_school_type_as_with_options("types", child, true)rows.facet("types")
TypeScriptfacetBySchoolTypeAs("types", child, true)rows.facet("types")
SwiftfacetBySchoolTypeAs("types", child, includeAllFacets: true)rows.facet("types")
Pythonfacet_by_school_type_as("types", child, include_all_facets=True)rows.facet("types")
C#/.NETFacetBySchoolTypeAs("types", child, includeAllFacets: true)rows.Facet("types")
GoFacetBySchoolTypeAs("types", child, true)rows.Facet("types")

Use the same normalized outer filter for page rows, totals, aggregates, and Facets when they are meant to describe one screen. A Facet request does not bypass context policy or authorization.

Mutation: change a graph at one audited boundary​

Create, update, and deletion use one lifecycle:

  1. Create from a generated Request carrying both comment and purpose, or query the current entity before updating.
  2. Change fields and relationships through generated methods.
  3. Use markForDeletion/language equivalent to record deletion intent.
  4. Attach a non-empty audit reason.
  5. Save the graph with trusted context and retain the returned entity.

Checker and Fix run before provider mutation. Optimistic version checks reject stale updates. Deletion intent is committed by the same audited save boundary; it is not a separate unaudited delete channel. See the cross-language Mutation lifecycle for the graph, validation, audit, and retry semantics.

Language examples​

The scenario page for each language introduces the individual operations. Its advanced page then composes them into a search screen, a relation graph with per-parent Top-N, analytics, Facets, and an audited read-modify-save workflow:

LanguageScenariosAdvanced composition
JavaJava business scenariosJava advanced data operations
RustRust business scenariosRust advanced data operations
TypeScriptTypeScript business scenariosTypeScript advanced data operations
SwiftSwift business scenariosSwift advanced data operations
PythonPython business scenariosPython advanced data operations
C#/.NET.NET business scenarios.NET advanced data operations
GoGo business scenariosGo advanced data operations

Names such as School, SchoolType, and studentCapacity come from the audited School Management fixture. Your model generates different names. Use current Assist or generated Request source to obtain the exact methods; do not translate a method name from another language by hand.