@DerivedField¶
@DerivedField marks a static callback that produces a value stored with the
model. The generated model evaluates the callback, and the entity exposes the
persisted value through DerivedFieldSchema for filtering or ordering.
Use a derived field when the value needed by a query is calculated from one or more model properties, such as normalized text, a combined search value, or a structured value.
The callback name must use the reserved $dorm$derived$ prefix. The suffix
becomes the generated getter and schema field name. name identifies the
persisted storage name; when omitted, the suffix is used.
@Model(name: 'users', as: #users)
abstract class _User {
@Field(name: 'username')
String get username;
@DerivedField(name: '_query/username')
static String $dorm$derived$qUsername(
_User model,
DerivedTransformations transformations,
) => transformations.text(model.username) ?? '';
}
The generated model has a qUsername getter and persists its value at
_query/username. Query the generated field metadata:
final users = await dorm.users.repository.peekAll(
Filter.text(
'ADA',
field: UserEntity.fields.qUsername,
),
);
Callback signature¶
Every derived callback must:
- be declared directly on the annotated model class;
- be
static; - use exactly two required positional parameters;
- receive the annotated model type first;
- receive
DerivedTransformationssecond; - return a synchronous, non-
voidvalue.
The generator rejects methods with incompatible signatures, inherited methods, top-level functions, and asynchronous return types. The callback body is not analysed for complete serializability; the returned value must be accepted by the project's serialization and database engine.
Combining values¶
The callback controls composition directly. There is no token list and no automatic separator:
@DerivedField(name: '_query/address')
static String $dorm$derived$qAddress(
_Address model,
DerivedTransformations transformations,
) => '${model.zipCode}_${model.number}';
Use the generated field in a query through its FieldSchema:
final addresses = await dorm.addresses.repository.peekAll(
Filter.value(
'99950_13',
field: AddressEntity.fields.qAddress,
),
);
Built-in transformations¶
DerivedTransformations provides the normalization helpers used by the
previous token-based API. Each method returns a nullable String, so the
callback decides how a null source should be represented.
| Method | Result |
|---|---|
text |
Removes spaces, replaces supported diacritics, and uppercases text. |
enumeration |
Uses an enum's name or normalizes enum-like values. |
date |
Formats a date as YYYYMMDD. |
datetime |
Formats local date and time as YYYYMMDDHHmmssSSS. |
@DerivedField(name: '_query/created-at')
static String $dorm$derived$qCreatedAt(
_Event model,
DerivedTransformations transformations,
) => transformations.datetime(model.createdAt) ?? '';
The callback may also return a number, boolean, list, map, date, or null
when the configured serialization and engine support that representation.
Storage paths and persistence¶
A simple name creates a direct stored field. A name with one root and one
child segment, such as _query/username, preserves that nested shape where the
engine supports it. The generated value is included in model serialization and
is written when the model is persisted.
@DerivedField does not create a database index or run as a server-side query
expression. When source properties change, the model must be persisted again so
the stored derived value is updated.
Use Using filters for query examples.