Site ↗
Documentation sections
Concepts · 0.8.1

Virtual entities: selected fields and nested collections

Build API responses from existing records, with separate conditions, search and ordering for their parts.

On this page

A virtual entity, or projection, builds a response from selected fields of an existing persistent entity. For example, return a page block together with page data and its items. No new table is created and no data copied.

Responses can include source fields, direct belongsTo relationships and bounded hasMany/manyToMany collections. Virtual entities are read-only.

Selecting fields in the UI

Open Content → New entity, select virtual and its source persistent entity. Enter a name and module. Under Fields → Configure fields, select root fields and necessary direct relationships, then Finish.

Selected fields may have output aliases. These change API response names, not database columns. All output names must be unique.

Search, filters and ordering

Enable Searchable, Filterable and Sortable for suitable scalar fields. Configure these independently on the projection: source-field flags are not inherited. Search supports string and text.

BelongsTo fields participate in root-list search and filtering; sorting them changes root-record order. Each collection has its own Default limit, Maximum limit, default order and permitted field operations.

For example, sorting pageItems by position orders items separately within each block. The primary key stabilizes order when values are equal.

Records available through external API

Access contains Entity CRUD access, External READ access and Generated routes. External read rules are separated by source, direct belongsTo relationships and selected collections. Combine conditions within each section using AND/OR.

For blocks of published pages with visible items:

  • Page.status = published limits the pages associated with blocks.
  • PageBlock.isVisible = true keeps visible blocks.
  • PageItems.isVisible = true AND bodyMarkdown != an empty string selects items within each block.

The last rule does not hide a block without matching items: it retains an empty collection.

Add conditions with + Add. The icon before the trash button wraps a condition in a group; the trash button removes the condition or group. An empty text value means "", not NULL.

Rules belong to the virtual entity independently and are not inherited from source APIs. They restrict external list/get without changing administrative reads.

Viewing the result

After Generate and updating the application, open the virtual entity in the admin. The list displays selected fields; Details displays related data. Collections support their permitted search, filters, sorting and pagination. Edit records through their persistent entity.

Conditions from an API client

Root lists use limit, offset, searches, filters, sort, order. A collection aliased pageItems uses pageItemsLimit, pageItemsOffset, pageItemsSearches, pageItemsFilters, pageItemsSort, pageItemsOrder.

pageItemsSort=position&pageItemsOrder=asc
pageItemsFilters=[{"field":"title","op":"ne","value":""}]

Client filters use selected fields' output names; generator rules use source names. Client conditions are added to mandatory rules and cannot override them.

The server filters first, counts total, then paginates. Within one list request, collection parameters are the same for every parent. Admin Details provides separate collection controls.

Changing a projection

Projections cannot edit nested records. Selected direct relationships are supported; arbitrary response expansion or projections based on another projection are not. Collections are loaded in batches: one HTTP request does not necessarily mean one SQL query.

After changing fields, rules or models, Generate and restart the application. Review selections when changing source. An invalid field or rule reference produces a save/generation error rather than being silently removed.

Steps: Content: virtual entities, Content: access. For automation, use CLI: projections.