I\'m in the process of writing my first CQRS application, let\'s say my system dispatches the following commands:
Another option that comes to my mind is:
In your read side, you first build normalized views by events from the write side.
E.g.:
contingents table:
-----------
id, name
teams table:
-----------
id, name
contigents_teams table:
-----------
contigent_id, team_id
On ContingentCreated event, you just insert the record into the contingents table.
On TeamCreated event, you just insert the record into the teams table.
On TeamAssignToContingent event, you insert the record into the contigents_teams table.
On TeamNameChanged event, you update appropriate record in the teams table.
And so on.
Thus, your data is (eventually) consistent and in sync with the write side.
Yes, you need to use joins in the read side to fetch data...
If this normalized view does not satisfy read performance needs, then you can build a denormalized view from this normalized data. it requires an extra step to build the denormalized view, but to me, it is the most simple solution I can think of for now.
Maybe you even will not need a denormalized view.
After all (in my opinion), the main value of ES is capturing user intent, confidence in your data (no destructive operations, single source of truth), ability to answer questions that nobody could think of in the past, big value for analytics.
As I said, if you need to optimize performance, you always can build a denormalized view from the normalized view of the read side.