Is it a good idea to implement CQRS Read model as an Aggregate? Or the read model should be kept as a POCO class?
2 Answers
In general when using CQRS you also use an event sourced design, so you don't have DDD entities (and by extension aggregates - at all). Usually when using CQRS, you usually have a "command model" & a "query/read model" where the "command model" is some event queue that you may "snapshot" every X amount of time; and your query model(s) are just use case optimized search data stores where you aren't really interested in modelling a whole aggregate.
Now, even if you aren't using an event sourced system, and you are using DDD with just several "query/read models", chances are you want to create a DDD model and have aggregates on the "command model" and not the "read model", as your "command model" represents your domain view & understanding of your domain reflecting your (DDD) ubiquitous language. The read/query model(s) are more oriented towards fine tuning performance for particular use cases (fast searches in a product catalog for example); or for enriching/aggregating data with other "external-bounded context" information.
As a side note, it is important to note that even though your query/read model is not intended to match 1:1 your aggregate, there is usually some correlation between your command aggregate, and your model DTO.
Is it a good idea to implement CQRS Read model as an Aggregate?
Not really?
An AGGREGATE is a cluster of associated objects that we treat as a unit for the purposes of data change.
Since queries don't change the data, an aggregate is unnecessary ceremony. Putting a bunch of business data into an object just to take the data back out again doesn't make a lot of sense. Using a POCO/POJO/plain data structure gets the job done.

- 52,766
- 5
- 49
- 91
-
Quries don't change the object, but read model event handlers do. – DmitriBodiu Aug 12 '19 at 12:50
-
Queries not changing data aren't the reason why aggregates aren't DTOs. It is true that aggregates are sets of related data with Identity accessed trough a root, treated as a unit which establishes a transactional boundary of change; they can be queried internally or changed/deleted; but that doesn't have anything to do with the reason why they aren't mapped to the outer API contract; the reason why aggregates aren't related to the search model, is to provide an API contract independent of internal details, hiding those details and protecting the API from the evolution of the domain model. – tony _008 Aug 12 '19 at 19:20