Expressions
Expressions define values in the Projection Declaration Language. They can reference event properties, event context, literals, and create formatted strings.
Expression Types
Section titled “Expression Types”Property Paths
Section titled “Property Paths”Access properties from the event using dot notation:
nameemailaddress.citycontactInfo.emailorder.customer.nameExamples:
from UserRegistered Name = name Email = contactInfo.email City = address.cityEvent Context
Section titled “Event Context”Access event metadata using $eventContext.{property}:
$eventContext.occurred$eventContext.sequenceNumber$eventContext.correlationId$eventContext.eventSourceIdAvailable Properties:
occurred- When the event occurred (timestamp)sequenceNumber- Sequence number in the event streamcorrelationId- Correlation ID for tracking related operationseventSourceId- The event source identifier
Examples:
from OrderPlaced PlacedAt = $eventContext.occurred Sequence = $eventContext.sequenceNumber Correlation = $eventContext.correlationIdSee Event Context for more details.
Event Source ID Shorthand
Section titled “Event Source ID Shorthand”Quick access to the event source identifier:
$eventSourceIdThis is equivalent to $eventContext.eventSourceId.
Example:
from UserAssignedToGroup GroupId = $eventSourceId UserId = userIdIdentity (Caused By)
Section titled “Identity (Caused By)”Access the identity that caused the event using $causedBy:
$causedBy.subject$causedBy.name$causedBy.userNameAvailable Properties:
subject- The identifier of the identity (unique ID)name- Display name of the identityuserName- Username of the identity
Examples:
from OrderPlaced CreatedBySubject = $causedBy.subject CreatedByName = $causedBy.name CreatedByUser = $causedBy.userName
from DocumentUpdated UpdatedBy = `${$causedBy.name} (${$causedBy.userName})` UpdatedById = $causedBy.subjectLiterals
Section titled “Literals”Direct values of various types:
Boolean:
IsActive = trueIsDeleted = falseString:
Status = "Pending"Category = "Electronics"Number:
Count = 0Price = 99.99Tax = 0.08Null:
OptionalField = nullExamples:
from AccountCreated Balance = 0.0 IsActive = true Status = "New" Notes = nullString Templates
Section titled “String Templates”Create formatted strings with embedded expressions:
`${expression}``${firstName} ${lastName}``Order: ${orderNumber}`Syntax:
- Wrap in backticks:
` - Use
${...}for expression substitution - Can include multiple expressions
Examples:
from PersonRegistered FullName = `${firstName} ${lastName}` DisplayInfo = `${name} (${email})`
from OrderPlaced Reference = `ORD-${orderNumber}` Summary = `Order ${orderNumber} for ${customerName}`Expression Context
Section titled “Expression Context”Expressions are evaluated in different contexts:
Event Data Context
Section titled “Event Data Context”When mapping from events, expressions reference event properties:
from UserCreated Name = name # References event.name Email = email # References event.emailEvent Context
Section titled “Event Context”Special $eventContext provides metadata:
from UserCreated CreatedAt = $eventContext.occurred CreatedBy = $eventContext.eventSourceIdMixed Context
Section titled “Mixed Context”Combine event data with event context:
from OrderPlaced OrderNumber = orderNumber # Event data PlacedAt = $eventContext.occurred # Event context Reference = `${orderNumber}-${$eventContext.sequenceNumber}` # BothExpression Compilation
Section titled “Expression Compilation”The declaration syntax is transformed when compiled into Chronicle projection definitions:
| Declaration Syntax | Compiled Format | Description |
|---|---|---|
name | name | Event property remains unchanged |
address.city | address.city | Nested properties remain unchanged |
$eventContext.occurred | $eventContext(occurred) | Dot notation becomes function-style |
$eventSourceId | $eventSourceId | Remains unchanged |
true | true | Literals remain unchanged |
`${name}` | `${name}` | Templates remain unchanged |
This transformation ensures compatibility with Chronicle’s internal expression format while keeping the declaration syntax clean and intuitive.
Type Compatibility
Section titled “Type Compatibility”Expressions must be compatible with the target property type:
public class UserReadModel{ public string Name { get; set; } // Requires string public int LoginCount { get; set; } // Requires number public bool IsActive { get; set; } // Requires boolean public DateTime CreatedAt { get; set; } // Requires timestamp}Valid:
Name = name # stringLoginCount = 0 # numberIsActive = true # booleanCreatedAt = $eventContext.occurred # timestampInvalid:
Name = 123 # number to string (invalid)LoginCount = "five" # string to number (invalid)IsActive = "yes" # string to boolean (invalid)Nested Property Access
Section titled “Nested Property Access”Access deeply nested properties:
from OrderPlaced CustomerEmail = order.customer.contactInfo.email ShippingCity = order.shipping.address.city BillingStreet = billing.address.line1Expressions in Different Contexts
Section titled “Expressions in Different Contexts”Property Assignments
Section titled “Property Assignments”Property = expressionExamples:
Name = nameTotal = order.totalCreatedAt = $eventContext.occurredDisplayName = `${firstName} ${lastName}`key expressionExamples:
from UserCreated key userIdfrom OrderPlaced key $eventSourceIdfrom LineItem key order.idComposite Keys
Section titled “Composite Keys”key Type { Property = expression ...}Examples:
key OrderLineKey { OrderId = orderId LineNumber = lineNumber Sequence = $eventContext.sequenceNumber}Arithmetic Operations
Section titled “Arithmetic Operations”add Property by expressionsubtract Property by expressionExamples:
add Balance by amountsubtract Stock by quantityadd Total by lineItem.totalParent Keys
Section titled “Parent Keys”parent expressionExamples:
parent groupIdparent $eventContext.eventSourceIdparent order.customerIdChild Identifiers
Section titled “Child Identifiers”id expressionExamples:
children members identified by userIdchildren items identified by lineNumberchildren versions identified by $eventContext.sequenceNumberBest Practices
Section titled “Best Practices”- Use Property Paths: Directly access nested properties rather than mapping intermediate objects
- Event Context for Metadata: Use
$eventContextfor timestamps, IDs, and correlation - Templates for Display: Create formatted display values with templates
- Literals for Defaults: Set initial values with appropriate literal types
- Type Awareness: Ensure expressions produce values compatible with target properties
- Shorthand When Clear: Use
$eventSourceIdshorthand for clarity - Null Handling: Use
nullliteral for optional fields
Common Patterns
Section titled “Common Patterns”Audit Fields
Section titled “Audit Fields”CreatedAt = $eventContext.occurredCreatedBy = $eventContext.eventSourceIdLastUpdated = $eventContext.occurredVersion = $eventContext.sequenceNumberDisplay Values
Section titled “Display Values”FullName = `${firstName} ${lastName}`Address = `${street}, ${city}, ${state} ${zipCode}`Summary = `${product} x ${quantity} @ ${price}`Nested Access
Section titled “Nested Access”Email = contact.emailPhone = contact.phoneNumbers.primaryCity = addresses.shipping.cityDefault Values
Section titled “Default Values”Status = "Pending"IsActive = trueCount = 0Balance = 0.0Notes = nullSee Also
Section titled “See Also”- Event Context - Detailed event context properties
- Property Mapping - Using expressions in mappings
- Keys - Expressions in key definitions