使用 CQRS 和 ES 跨多个聚合进行命令

Command accros multiple aggregates with CQRS and ES

我在思考问题的解决方案时遇到了一个奇怪的案例。

快速回顾一下:我正在使用带有 CQRS 的事件存储,我有 2 个聚合,分别称为 'Group' 和 'User'。

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

然后他可以选择 'match' 与同一地区、相同年龄和相同兴趣的小组。

现在情况是这样的:'matchmaking' 部分应该完全发生在后端,它可能是一个很长的 运行 过程,但对于客户端来说,它只是对端点的 1 次调用和结束结果应该是他匹配到一组。

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

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

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

所以 I:m 有点卡在这里,有些东西告诉我,一个漫长的 运行 过程/传奇可能是我问题的答案,但我不明白我为什么仍然不会在我的 saga 中打破查询和命令的混合,因为 saga 基本上是 commands/events.

的链

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

嗨,这实际上是 CQRS 大放异彩的案例。

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

所以,

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

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

内存中的图形可能会很好。

-克里斯

p.s.

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

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

例如

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

-克里斯