gpt4 book ai didi

domain-driven-design - 通过多个聚合从域事件重建查询

转载 作者:行者123 更新时间:2023-12-02 03:30:17 26 4
gpt4 key购买 nike

我正在使用DDD / CQRS / ES方法,并且对建模聚合和查询有一些疑问。例如,请考虑以下情形:

用户可以创建工作项,更改其标题并将其他用户关联到该工作项。 WorkItem具有参与者(关联用户),并且参与者可以将操作添加到WorkItem。参与者可以执行动作。

让我们假设已经创建了Users,并且我只需要userIds。

我有以下WorkItem命令:

  • CreateWorkItem
  • 更改标题
  • 添加参与者
  • AddAction
  • ExecuteAction

  • 这些命令必须是幂等的,因此我不能将同一用户或操作添加两次。

    和以下查询:
  • WorkItemDetails(工作项的所有信息)

  • 查询由处理程序更新,这些处理程序处理由WorkItem集合引发的域事件(将它们保留在EventStore中之后)。所有这些事件都包含WorkItemId。如果需要,我希望能够通过加载所有相关事件并按顺序处理它们来即时重建查询。这是因为我的用户通常不会访问一年前创建的WorkItem,因此我不需要处理这些查询。因此,当我获取一个不存在的查询时,可以重建它并将其存储在具有TTL的键/值存储中。

    域事件具有一个aggregateId(用作事件streamId和shard键)和一个sequenceId(用作事件流中的eventId)。

    因此,我的第一个尝试是创建一个名为WorkItem的大型聚合,其中包含参与者和操作集合。参与者和动作是仅存在于WorkItem中的实体。参与者引用一个userId,而动作引用一个参与者id。他们可以获取更多信息,但这与本练习无关。使用此解决方案,我的大型WorkItem集合可以确保命令是幂等的,因为我可以验证自己没有添加重复的参与者或动作,并且如果我想重建WorkItemDetails查询,则只需加载/处理给定事件的所有事件即可。 WorkItemId。

    之所以能正常工作,是因为因为我只有一个聚合,所以WorkItemId可以是gregationId,因此当我重建查询时,我只会加载给定WorkItemId的所有事件。
    但是,此解决方案具有大量聚合的性能问题(为什么要加载所有参与者和操作来处理ChangeTitle命令?)。

    因此,我的下一个尝试是使用不同的聚合,所有聚合都具有与属性相同的WorkItemId,但只有WorkItem聚合才将其作为AggregationId。这解决了性能问题,我可以更新查询,因为所有事件都包含WorkItemId,但是现在我的问题是我无法从头开始重建它,因为我不知道其他聚合的aggregateId,因此无法加载他们的事件流并对其进行处理。它们具有WorkItemId属性,但这不是其真正的aggregateId。另外,我不能保证我按顺序处理事件,因为每个聚合都将有自己的事件流,但是我不确定这是否是一个真正的问题。

    我可以想到的另一个解决方案是拥有专用的事件流,以合并由多个聚合引发的所有WorkItem事件。因此,我可以使用事件处理程序,将事件和操作所引发的事件简单地附加到事件流中,该事件流的ID类似于“{workItemId}:allevents”。这将仅用于重建WorkItemDetails查询。这听起来像是黑客。.基本上,我正在创建没有业务操作的“聚合”。

    我还有什么其他解决方案?快速重建查询是否不常见?将多个聚合(多个事件流)的事件用于构建同一查询时,可以完成吗?我已经搜索了这种情况,但没有发现任何有用的信息。我觉得我想念的东西应该很明显,但是我还没弄清楚。

    非常感谢对此的任何帮助。

    谢谢

    最佳答案

    我认为您在设计汇总时不应考虑查询问题。 Read端就是为此。

    在域方面,应关注一致性问题(聚合可以有多小,并且域在单个事务中仍保持一致),并发性(可以有多大并且不会遇到并发访问问题/竞争条件?)和性能(请问)我们将数以千计的对象加载到内存中只是为了执行简单的命令-正是您要的内容)。

    我认为按需读取模型没有任何问题。除了在需要时重新创建流之外,它与从实时流中读取基本上相同。但是,这可能是很多工作,而不是获得非凡的收益,因为在大多数情况下,实体是在修改后立即查询的。如果按需变为“基本上每次实体更改”,那么您也可以订阅实时更改。对于“旧” View ,“旧”的定义是不再对其进行修改,因此无论您是按需系统还是连续系统,都无需重新计算它们。

    如果您走了多个小型集合路线,并且您的读取模型需要来自多个来源的信息来进行自我更新,则有两种选择:

  • 使用其他数据丰富发射事件
  • 从多个事件流读取并合并其数据以构建读取模型。这里没有魔术,读方需要知道特定投影中涉及哪些聚合。如果您知道其他读取模型是最新的,并且仅会提供所需的数据,您也可以查询它们。

  • 参见 CQRS events do not contain details needed for updating read model

    关于domain-driven-design - 通过多个聚合从域事件重建查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27325304/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com