Keys
Keys identify individual projection instances. They determine which read model instance to create or update when an event occurs.
Explicit Keys
Section titled “Explicit Keys”Specify which property from the event identifies the instance:
from UserRegistered key userId Name = name Email = emailThe userId from the event becomes the key for the UserReadModel instance.
Inline Key Syntax
Section titled “Inline Key Syntax”Keys can be specified inline on the from statement:
from OrderPlaced key orderId Total = total Status = "Pending"Multiple Events with Keys
Section titled “Multiple Events with Keys”When using multiple events in one from statement, each can have its own key:
from EventA key idA, EventB key idB, EventC automapBlock Key Syntax
Section titled “Block Key Syntax”For more complex scenarios, use block syntax:
from OrderPlaced key orderId Total = totalComposite Keys
Section titled “Composite Keys”Use composite keys when multiple properties together identify an instance:
from OrderCreated key OrderKey CustomerId = customerId OrderNumber = orderNumber Total = totalComposite Key Structure
Section titled “Composite Key Structure”key {TypeName} {Property} = {expression} {Property} = {expression} ...The {TypeName} must match a complex type defined in your read model schema.
Composite Key with Event Context and Causation
Section titled “Composite Key with Event Context and Causation”You can include event context and causation values in composite keys:
from LineItemAdded key LineItemKey OrderId = orderId LineNumber = lineNumber SequenceNumber = $eventContext.sequenceNumber CreatedBy = $causedBy.subject Product = productName Quantity = quantityDefault Key Behavior
Section titled “Default Key Behavior”If no key is specified, the event source ID is used as the key:
from UserRegistered Name = nameEquivalent to:
from UserRegistered key $eventSourceId Name = nameKey in Children
Section titled “Key in Children”Children must always specify an identifier:
children members identified by userId from UserAddedToGroup key userId parent groupId Role = roleThe id userId specifies the child identifier property, while key userId specifies which event property to use.
Key Expressions
Section titled “Key Expressions”Keys can be:
- Property paths:
userId,order.id,data.customerId - Event source ID:
$eventSourceId - Event context:
$eventContext.correlationId
Examples
Section titled “Examples”Simple Key
Section titled “Simple Key”from ProductCreated key productId Name = name Price = priceEvent Source as Key
Section titled “Event Source as Key”from AccountCreated key $eventSourceId AccountNumber = accountNumber Balance = 0.0Nested Property as Key
Section titled “Nested Property as Key”from OrderPlaced key order.id Total = order.total CustomerId = customerIdComposite Key Example
Section titled “Composite Key Example”projection OrderLine => OrderLineReadModel from LineItemAdded key OrderLineKey { OrderId = orderId ProductId = productId } Quantity = quantity UnitPrice = unitPrice LineTotal = totalComposite Key with Multiple Properties
Section titled “Composite Key with Multiple Properties”from ReservationMade key ReservationKey { HotelId = hotelId RoomNumber = roomNumber CheckInDate = checkInDate } GuestName = guestName Nights = nightsChildren with Keys
Section titled “Children with Keys”children orderLines identified by lineNumber from LineItemAdded key lineNumber parent orderId Product = productName Quantity = quantity Price = priceLiteral (Constant) Keys
Section titled “Literal (Constant) Keys”Use literal "value" to fix the key to a constant string. All events matching the from block update the same read model instance regardless of event source:
from OrderPlaced key literal "global" count TotalOrdersEvery OrderPlaced event, from every event source, increments TotalOrders on the single document with key "global".
Inline literal syntax
Section titled “Inline literal syntax”Literal keys also work inline on the from statement:
from UserLoggedIn key literal "site-stats" count TotalLoginsCombining literal keys with functions
Section titled “Combining literal keys with functions”Literal keys are especially useful with counter and arithmetic operations for global aggregates:
projection SiteMetrics => SiteMetricsReadModel from UserRegistered key literal "metrics" count TotalUsers
from UserLoggedIn key literal "metrics" increment ActiveSessions
from UserLoggedOut key literal "metrics" decrement ActiveSessions
from OrderPlaced key literal "metrics" count TotalOrders add TotalRevenue by amountAll events from all users accumulate into the single SiteMetricsReadModel document with key "metrics".
When to Use Each Approach
Section titled “When to Use Each Approach”Simple Keys (inline):
- Single property identifies the instance
- Property name is clear from context
- Most common scenario
Block Keys:
- When you want visual separation
- Complex event structures
- Personal preference for readability
Composite Keys:
- Multiple properties together form identity
- Natural keys from business domain
- Partitioning or sharding scenarios
- Complex relationships
Event Source ID:
- Each event stream represents one instance
- Aggregate-based event sourcing
- One-to-one event stream to read model
Literal (Constant) Keys:
- All events update the same instance
- Global counters and system-wide aggregates
- Singleton read models
Best Practices
Section titled “Best Practices”- Be Explicit: Specify keys when not using event source ID
- Match Domain: Use business-meaningful identifiers
- Composite for Complexity: Use composite keys for multi-property identifiers
- Consistent Naming: Use consistent key property names across events
- Document Composites: Composite keys benefit from clear type names
- Literal for Globals: Use literal keys for system-wide or global aggregates