CQRS(事件来源):具有多个汇总的投影 [英] CQRS (event sourcing): Projections with multiple aggregates

查看:137
本文介绍了CQRS(事件来源):具有多个汇总的投影的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我对CQRS体系结构中涉及多个集合的投影有疑问。



例如,假设我有两个集合 WorkItem code>和 Developer ,并且以下事件顺序发生(但不是立即发生)


  1. WorkItemCreated(workItemId)

  2. WorkItemTitleChanged(workItemId,标题)

  3. DeveloperCreated(developerId)

  4. DeveloperNameChanged(developerId,名称)

  5. WorkItemAssigned(workitemId,DeveloperId)

我希望创建一个作为开发人员工作项的内部联接的投影:

  | WorkItemId | DeveloperId |标题|开发者名称| ... | 
| ------------ | ------------- || -------- | --------- ------ | ----- |
| 1 | 1 | FixBug |约翰·杜... |

我做预测的方式是逐步的。意思是我从数据库中加载了保存的投影并应用了剩余的事件。



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



为了在<$ c时获得所需信息$ c> WorkItemAssigned ,我必须从事件存储中加载所有 all 事件,将所有 WorkItems的 states 保留在内存中 Developers ,所以在 WorkItemAssigned 事件到达时,我已经掌握了必需的信息。 / p>

当然,我可以为 Workitem 作一个投影,为 Developer 并查询它们以获取其最后状态。但这似乎是一项艰巨的工作,如果我要为每个聚合分别创建投影,我也可以创建一个数据库视图来 inner-join (事实上,这就是我在做的。)



我并没有手动完成所有操作,我目前正在使用一个名为 EventFlow ,但这并没有指引我回答这个问题。



这是有关CQRS基本原理的问题,并且我跌倒了,我在这里缺少任何东西。

解决方案

我认为您没有丢失任何东西。与基于关系模型的查询相比,在基于事件的系统中投影读取的模型会带来不同的问题。问题不是不必要容易解决或难以解决;他们只是不同



好消息是您有很多选择。通过事件搜索,您可以以任何可以想象的方式投影数据,因此您可以决定最适合每种投影的解决方案。我猜这是一个坏消息(我认为这不是一个坏消息)是,该问题的解决方案与关系系统(每次使用JOIN构造查询)的解决方案都不相同。



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




  • 使用关系模型作为其中一种您读取的模型

  • 发生某种类型的事件时,重新查询保存所需数据的流,并使用它们按需投影



您还可以简单地将一些数据保持为临时状态(在内存,文档数据库,文件系统等中),从而可以查找数据和项目需要的时候。因此,请保留更新的WorkItems和Developers的列表,以便在出现WorkItemAssigned事件时可以读取和使用它们。



我想说,将关系数据库创建为临时或永久读取假设您不是要实现大规模的可伸缩性,模型就是解决问题的一种完全可行的方法。


I have a question regarding projections involving multiple aggregates on a CQRS architecture.

For example sake, suppose I have two aggregates WorkItem and Developer and that the following events happen sequentially (but not immediately)

  1. WorkItemCreated (workItemId)
  2. WorkItemTitleChanged (workItemId, title)
  3. DeveloperCreated (developerId)
  4. DeveloperNameChanged (developerId, name)
  5. WorkItemAssigned (workitemId, DeveloperId)

I wish to create a projection which is as "inner join" of developer-workitem:

| WorkItemId | DeveloperId | Title  | DeveloperName | ... |
|------------|-------------|--------|---------------|-----|
| 1          | 1           | FixBug | John Doe      | ... |

The way I am doing my projections is incrementally. Meaning I load the saved projections from the database and apply the remaining events as they come.

My problem is, the event responsible for creating a row on the projection table is WorkItemAssigned. However, that event does not carry required information from previous events (workitem title, developer name, etc.)

In order to have the required information by the time WorkItemAssigned, I have to load all events from the eventstore, keep states in-memory for all WorkItems and Developers so I have the required information by the time a WorkItemAssigned event arrives.

Sure, I could have a projection for Workitem, another for Developer and query them to retrieve their last states. But it seems like a lot of work, if I am to create projections for each aggregate separately, I might as well create a database view to inner-join them (In fact, that is what I am doing.)

I am not doing all this by hand, I am currently using a good framework called EventFlow, but it doesn´t direct me to answer this question.

This is a question on fundamentals of CQRS, and I fell I am missing something here.

解决方案

I don't think you are missing anything. Projecting read models in an event-sourced system presents a different set of problems than querying from a relational model. The problems are not necessarily easier or harder to solve; they are just different.

The good news is that you have a lot of choices. Event Sourcing allows you to project data in any imaginable way, so you can decide on a solution that is most suitable for each individual projection. I guess the "bad" news (I would argue it's not bad news) is that the solution to the problem is not the same every time as it is with a relational system, which is to construct a query using JOINs.

You've already identified a few possible solutions:

  • Use a relational model as one of your read models
  • When a certain type of event comes in, re-query the streams that hold the data you need and use them to project on demand

You could also simply hold some data in an interim state (in memory, a document database, the file system, etc.) that allows you to look up the data and project it when needed. So keep lists of updated WorkItems and Developers where they can be read and used whenever a WorkItemAssigned event comes in.

I would say creating a relational database as an interim or permanent read model is a perfectly viable way of solving the problem, assuming you are not trying to achieve massive scalability.

这篇关于CQRS(事件来源):具有多个汇总的投影的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆