CQRS(事件来源):具有多个汇总的投影

Fab*_*eco 6 cqrs event-sourcing

我有一个关于在CQRS体系结构上涉及多个聚合的投影的问题。

例如,假设我有两个聚合WorkItemDeveloper并且以下事件顺序发生(但不是立即发生)

  1. WorkItemCreated(workItemId)
  2. WorkItemTitleChanged(workItemId,标题)
  3. DeveloperCreated(developerId)
  4. DeveloperNameChanged(developerId,名称)
  5. WorkItemAssigned(workitemId,DeveloperId)

我希望创建一个作为developer-workitem的“内部连接”的投影:

| WorkItemId | DeveloperId | Title  | DeveloperName | ... |
|------------|-------------|--------|---------------|-----|
| 1          | 1           | FixBug | John Doe      | ... |
Run Code Online (Sandbox Code Playgroud)

我做预测的方式是逐步的。意思是我从数据库中加载保存的投影,并在剩余事件发生时应用它们。

我的问题是,负责在投影表上创建一行的事件是WorkItemAssigned。但是,该事件不携带先前事件的必需信息(工作项标题,开发人员姓名等)。

为了及时获取所需的信息WorkItemAssigned,我必须从事件存储中加载所有事件,将所有事件的状态保持在内存中WorkItemsDevelopers因此在WorkItemAssigned事件到达时我具有所需的信息。

当然,我可以为Workitem,另一个提供一个投影,Developer并查询它们以检索其最后状态。但是似乎要进行很多工作,如果我要分别为每个聚合创建投影,那么我不妨创建一个数据库视图以内部联接它们(事实上,这就是我正在做的事情。)

我并没有手动完成所有操作,我目前正在使用一个名为EventFlow的良好框架,但是它并没有指导我回答这个问题。

这是关于CQRS基本原理的问题,我倒是在这里漏了一些东西。

Phi*_*ler 7

我不认为你错过了什么。与从关系模型查询相比,在事件源系统中投影读取模型会带来一系列不同的问题。解决问题并不一定更容易或更难;解决起来并不一定容易。他们只是不同

好消息是您有很多选择。事件溯源允许您以任何可以想象的方式投影数据,因此您可以决定最适合每个单独投影的解决方案。我想“坏”消息(我认为这不是坏消息)是问题的解决方案每次都与关系系统不同,即使用 JOIN 构造查询。

您已经确定了一些可能的解决方案:

  • 使用关系模型作为您的读取模型之一
  • 当某种类型的事件到来时,重新查询保存所需数据的流并使用它们进行按需投影

您还可以简单地将一些数据保存在临时状态(在内存、文档数据库、文件系统等中),以便您可以查找数据并在需要时对其进行投影。因此,请保留更新的工作项和开发人员列表,以便每当发生 WorkItemAssigned 事件时都可以读取和使用它们。

我想说,假设您不试图实现大规模的可扩展性,那么创建一个关系数据库作为临时或永久读取模型是解决该问题的完全可行的方法。