2
votes

I want to create a new read model projection of my events in my CQRS/ES application.

The problem is that the key i need to use for my projection is not present in all my events :

My root aggregate is a Car.

  • First event is a CarCreated event holding the "manufacturer"

  • Then i shall have a CarRepaired event holding only a "date"

My new read projection is a CarsRepairedPerManufacturer which will count repaired cars for each manufacturer :

  • No problem for the CarCreated event : This event hold de "manufacturer" so my read view is created with the correct key

  • The problem is with my CarRepaired event : How can find the correct row in my read model (where the key is the manufacturer) when i don't have this information in my event ?

Maybe i am missing something here because if this was unsolvable it would limit the kind of projections you could do in ES/CQRS.

2

2 Answers

3
votes

Your question does not specifically mention DDD, but it is a very helpful paradigm to consider. CQRS/ES is not the impediment here.

You have hit upon a classic problem of context mingling. The context in which cars are created (or "built") doesn't care about what happens when they go for repair. The context in which the repairs happen doesn't really care about the process by which the car was built. Your single Car aggregate is attempting to serve two contexts at the same time, which is why you have this impedance mismatch and should provide you with pause to reconsider your design.

Are you sure you have drawn your aggregate boundary correctly, i.e. that a 'Car' needs to track both it's creation AND it's repair? Why not have a 'Car' aggregate and a 'Repair' aggregate?

2
votes

You have the ID of the manufacturer in the CarCreated event so you could get it from there.

The CarCreated event happens before the CarRepaired event so when you get the CarCreated event, save the ID of the manufacturer in the projection together with the CarID. Then when you get the CarRepaired event you can look up the ID of the manufacturer in the projection (if you are using an SQL DB you can create a new table for that). The projection can hold more than just the data that you want to show, it can also hold a state that is used for creating the projection itself.

Another option is to send the ID of the manufacturer with the CarRepaired event. You already have it in your aggregate from the CarCreated event. That way you do not have to create a new table in the database for just one lookup.