Property Mapping
Property mapping assigns values from events to read model properties. Mappings use the simple assignment syntax: Property = expression.
Basic Mapping
Section titled “Basic Mapping”Map an event property to a read model property:
from UserRegistered Name = name Email = emailThis maps the name and email properties from the UserRegistered event to the corresponding properties on the read model.
Nested Properties
Section titled “Nested Properties”Access nested properties using dot notation:
from UserRegistered Email = contactInfo.email Phone = contactInfo.phone City = address.cityLiteral Values
Section titled “Literal Values”Assign literal values:
from UserRegistered Name = name IsActive = true Status = "Pending" Priority = 5 CreatedAt = nullSupported literal types:
- Boolean:
true,false - String:
"text"(double quotes) - Number:
42,3.14 - Null:
null
Clearing a Value
Section titled “Clearing a Value”Assigning a value and removing one are different acts, and = hides the difference. Use clear to remove the value a property holds:
clear {Property}Example
Section titled “Example”from NoteCleared clear Note ClearedAt = $eventContext.occurredA dotted path clears a property on a nested object:
from OwnerNoteCleared clear Owner.NoteProperty = null means the same thing and keeps working, so nothing written against the older spelling breaks. Prefer clear in new projections — it names the act instead of assigning nothing.
clear <property> is a mapping line inside a from, every, all or with block. It is not the same directive as clear with <EventType>, which nulls a whole child object — see Nested Objects.
Because the two read alike, a bare clear with — the directive without its event type — is reported as an invalid mapping rather than read as clearing a property named with. If a read model really does have a property called with, escape it: clear @with.
String Templates
Section titled “String Templates”Create formatted strings using template literals:
from PersonRegistered FullName = `${firstName} ${lastName}` DisplayInfo = `${name} (${email})`Template syntax:
- Wrap in backticks:
`template` - Use
${expression}for substitutions - Can combine multiple expressions
Event Source ID
Section titled “Event Source ID”The special identifier $eventSourceId provides the event source ID:
from UserAssignedToGroup GroupId = $eventContext.eventSourceId UserId = $eventSourceIdEvent Context
Section titled “Event Context”Access event metadata:
from UserRegistered Name = name CreatedAt = $eventContext.occurred SequenceNumber = $eventContext.sequenceNumber CorrelationId = $eventContext.correlationIdSee Event Context for all available properties.
Multiple Mappings
Section titled “Multiple Mappings”Define multiple mappings in a single from block:
from OrderPlaced OrderNumber = orderNumber CustomerId = customerId Total = total Status = "New" PlacedAt = $eventContext.occurred TaxRate = 0.08Property Types
Section titled “Property Types”The read model property type determines what values are valid:
from ProductCreated Name = name # string Price = price # decimal/number IsAvailable = true # boolean Stock = 0 # integer Category = null # nullableExamples
Section titled “Examples”User Profile
Section titled “User Profile”from UserProfileUpdated FirstName = firstName LastName = lastName Email = email Bio = bio UpdatedAt = $eventContext.occurredOrder with Calculated Fields
Section titled “Order with Calculated Fields”from OrderPlaced OrderId = orderId CustomerId = customerId Subtotal = subtotal Tax = tax Total = total Status = "Pending" Reference = `ORD-${orderNumber}` PlacedAt = $eventContext.occurredNested Data
Section titled “Nested Data”from CompanyRegistered CompanyName = name Email = contactInfo.email Phone = contactInfo.phone Street = address.street City = address.city State = address.state ZipCode = address.zipCodeWith Literals and Context
Section titled “With Literals and Context”from AccountCreated AccountNumber = accountNumber Balance = 0.0 IsActive = true AccountType = "Standard" OpenedAt = $eventContext.occurred OpenedBy = $eventContext.eventSourceIdBest Practices
Section titled “Best Practices”- Be Explicit: Name properties clearly to show intent
- Use Defaults: Set initial values with literals when appropriate
- Leverage Context: Use event context for audit fields
- Templates for Display: Use templates to create formatted display values
- Nested Access: Directly access nested properties rather than mapping intermediate objects