我对CQRS架构上涉及多个聚合的投影有疑问。
例如,假设我有两个聚合WorkItem
和Developer
,并且以下事件顺序发生(但不是立即发生)
我希望创建一个作为developer-workitem的“内部联接”的投影:
| WorkItemId | DeveloperId | Title | DeveloperName | ... |
|------------|-------------|--------|---------------|-----|
| 1 | 1 | FixBug | John Doe | ... |
我做预测的方式是逐步的。意思是我从数据库中加载了保存的投影,并在剩余事件发生时应用它们。
我的问题是,负责在投影表上创建行的事件是WorkItemAssigned
。但是,该事件不包含以前事件的必需信息(工作项标题,开发人员姓名等)
为了在WorkItemAssigned
时获得所需的信息,我必须从事件存储中加载 all 个事件,将所有 states 保留在内存中WorkItems
和Developers
,所以在WorkItemAssigned
事件到来时,我已经掌握了必要的信息。
当然,我可以为Workitem
进行投影,为Developer
进行投影,并查询它们以检索其最后状态。但这似乎是一项艰巨的工作,如果我要为每个聚合分别创建投影,我也可以创建一个数据库视图以 inner-join (事实上,这就是我在做的)
我并没有手工做这一切,我目前正在使用一个名为EventFlow的良好框架,但这并没有指导我回答这个问题。
这是关于CQRS基本原理的问题,我跌倒了,我在这里遗漏了一些东西。
答案 0 :(得分:2)
我认为您没有丢失任何东西。与从关系模型中进行查询相比,在基于事件的系统中投影读取模型会带来一系列不同的问题。问题不是不必要容易解决或难以解决;它们只是不同。
好消息是您有很多选择。通过事件搜寻,您可以以任何可以想象的方式投影数据,因此您可以决定最适合每种投影的解决方案。我猜这是一个“坏”消息(我认为这不是一个坏消息)是,该问题的解决方案与关系系统(每次使用JOIN构造查询)的解决方案都不相同。
您已经确定了几种可能的解决方案:
您还可以简单地将某些数据保持为临时状态(在内存,文档数据库,文件系统等中),使您可以查找数据并在需要时对其进行投影。因此,请保留更新的WorkItems和Developers的列表,以便在出现WorkItemAssigned事件时可以读取和使用它们。
我想说,假设您不打算实现大规模的可伸缩性,则将关系数据库创建为临时或永久读取模型是解决该问题的一种完全可行的方法。