命令使用 CQRS 和 ES

问题描述

我在考虑解决问题的方法时遇到了一个奇怪的情况。

快速回顾:我正在使用带有 CQRS 的事件存储,并且我有 2 个名为“组”和“用户”的聚合。

基本上,用户定义了一些特征,例如他的地区、年龄和一些兴趣。

然后他可以选择与同一地区、年龄和兴趣相同的群组“匹配”。

现在是这样:“匹配”部分应该完全发生在后端,这可能是一个长时间运行的过程,但对于客户端来说,它只是对端点的 1 次调用,最终结果应该是他与一个组匹配.

因此,对于这种情况,我必须查询具有相同地区、相同年龄段的组,兴趣在我的查询中并不重要。我知道有一个组列表,媒人将根据组和用户间的共同兴趣给每个组一个评级。评分最高的小组将加入。

再次使用 CQRS 和 ES,我的问题是这种情况似乎是查询和命令的混合,将查询混合到匹配命令中似乎违背了 CQRS 的目的。

查询多个组并根据我的写入端(事件存储)过滤它们也是一个坏主意,因为必须重新构建聚合并将其加载到内存中,然后才能将它们过滤掉。

所以我:我有点卡在这里,有些东西告诉我长时间运行的进程/传奇可以解决我的问题,但我不明白我如何仍然不会打破查询和命令的混合我的传奇,作为一个传奇基本上是一连串的命令/事件。

我如何处理这个特定案例?不需要真正的代码,让我继续前进的概念性解决方案是完美的。

解决方法

嗨,这实际上是 CQRS 可以发挥作用的案例。

对于这种情况,创建专用匹配模型似乎是理想的选择,以允许以其他形式回答可能相当重要的查询。

所以,

  1. 创建一个专用(可能是临时的,可能是检查点/持久化)查询模型作为派生存储。
  2. 根据请求运行查询以获得最匹配的结果。
  3. 根据查询结果发送命令以使用新链接更新事件存储。

查询模型不需要管理命令,并且可以从事件存储推送的基础上更新。这将使构建和保持更新变得相当简单,并且可以进一步优化以仅包含此特定查询所需的数据。

内存中的图可能效果很好。

-克里斯

附上

在命令方面:这里的命令每个只会更新一个聚合实例。

进一步使用预写模式将允许不需要任何类型的进程管理器或“saga”。

例如

对于每个新成员,1 个命令将新成员添加到用户流,然后 1 个命令到组添加新成员信息。然后,一个简单的审计流程可以在启动/恢复时扫描不完整的成员资格分配,并作为定期数据质量检查。

-克里斯