Confusion about Projections and the Read Model with Event Sourcing

1,398 views
Skip to first unread message

Nick Chamberlain

unread,
Aug 16, 2016, 11:54:19 AM8/16/16
to DDD/CQRS
Hello everyone, first-time question-asker so thanks in advance :)

I'm trying to sort out my own confusion about how read models are designed and the definition of a projection in regards to the read model.

I understand all the benefits to storing events - history, no loss of data, immutability, etc.

But as far as the actual implementation - I'm kind of mixed up when I think about how we can take advantage of read model's ability to be "polyglot" - so we can have something like a denormalized, query-optimized storage on the read side that allows for much faster queries than if we had a normalized CRUD-style, single source of data for both sides.

Conceptually, when I think about what Event Sourcing is, I see that we can move past the "poison pill" architecture (ORM -> 3NF DB (Write Model) -> Queue -> Read Model) and start using the Event Store as the single source of truth in the system.  So the basic idea for the read model is to play back the Events for a given Aggregate to build the current state of the Aggregate, which requires denormalization using Projections... but I don't quite understand *when* this happens.

Does it happen when the user hits the UI and pulls up some data on the read side?  Do we ever query straight from Projections somehow (when people talk about "playback" and optimizing that using "snapshotting")?  Or, does denormalization/projection happen when the write model is sent a Command which then becomes an Event and then is eventually synchronized to the read model?  Is a Projection the same as a Denormalizer?  Is a Projection for querying or for denormalizing into a Read Model?  If the Projection is just an Event Handler, then does it even touch the Event Store at all?
So like:
Command -> Event -> Event Store
    \
      -> Projection -> Query-Optimized Store
Or
Command -> Event -> Event Store -> Poll (Read Model) -> Playback -> Projection -> Query-Optimized Store
Or
UI Request -> Query -> Playback -> Projection -> DTO -> UI Response

I guess I'm also a bit confused about GetEventStore's model of having Projections saved in JavaScript on the server - if a Projection is an Event Handler in code that denormalizes data for the Read Model, what are GetEventStore's Projections for?  Are they for Playback when something goes down and we need to rebuild the entire application's state?

Hope this makes sense, thanks!
- Nick

Greg Young

unread,
Aug 16, 2016, 3:36:35 PM8/16/16
to ddd...@googlegroups.com
Dont confuse GES projections with read models they are entirely different beasts
> --
> You received this message because you are subscribed to the Google Groups
> "DDD/CQRS" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to dddcqrs+u...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.



--
Studying for the Turing test

Nick Chamberlain

unread,
Aug 16, 2016, 4:29:50 PM8/16/16
to DDD/CQRS
Ah ok, good to know thanks.

I think I kind answered myself by re-watching your videos too. 

My confusion came from how to implement the Event Store as a queue for the Read Model.  I was missing the concept of the Event Store "pushing" events into a projection in an AMQP Pub/Sub style (but with CatchUpSubscription/Competing Consumers).  Missing this piece made me think projections didn't have to touch the Event Store, but just subscribe to the Write Model's events directly.

But if I were to use an Event Store to replace a message queue - the Write Model would push new events to the Event Store, the Read Model's projections would be subscribed to these new events and handle them (with checkpoints tracking last read Event), THEN save them down to the Read Model's storage.

So it's like:

Write Model ( Command -> Event -> Event Store ) -> Read Model ( Event Store -> Event -> Publish to Read Model Subscriber(s) -> Projection -> Save to Read Model Store )

Sound like I'm understanding it better?

Thanks,
Nick
Reply all
Reply to author
Forward
0 new messages