如何从事件存储中查询多个聚合?

How can I query for multiple aggregates from event store?

假设我正在通过事件溯源存储汽车。我有一个 CarAggregate,它可以 save/load 使用汽车 repo 正确地处理事件:

CarAggregateRepository
{
   CarAggregate GetById(Guid id)
   {
      var events = EventStore.LoadEventsById(id);
      var carAggregate = new CarAggregate(id);
      carAggregate.ApplyEvents(events);

      return carAggregate;
   }

   void Save(CarAggregate car)
   {
      EventStore.StoreEvents(car.Id, car.UncommittedEvents);
   }
}

我现在想要一种方法来查找匹配特定查询的汽车,例如,梅赛德斯制造的所有汽车:

List<CarAggregate> Find(string manufacturer)
{
   // What goes here?
}

我能想到的唯一方法是:

  1. 加载所有事件
  2. 构建所有聚合的列表
  3. 过滤列表以获得匹配的制造商

这肯定是非常低效的,因为我最终可能会从事件存储中加载数十万个单独的事件?这是大量的数据传输。此外,许多这些加载的聚合可能用于甚至不是 CarAggregates 的东西。也许他们是 UserAggregates,其事件也存储在同一个事件存储中?

我一定是漏掉了什么。如何列出所有匹配我的查询的 CarAggregates?

// What goes here?

通常的答案是读取模型的接口。

也就是说,您将有一些逻辑从您的事件存储中获取事件,并从中获取事件 creates/updates 一份报告,其中包含您在某些 shape/data structure/persistence 存储中需要的信息这使得查询更容易(因此:CQRS)。

一个常见的答案是有一个订阅事件存储的进程,也就是说它监听变化,查询存储以获取新事件的副本,然后更新一些 RDBMS 中的行,您可以用于生成报告。

您可以将报告视为事件存储中信息的缓存副本。信息会有点陈旧(这部分取决于您愿意花多少钱来减少延迟)。

您可以获取事件存储的检查点,然后遍历该检查点之前的所有事件,找出哪些汽车与您的查询匹配,但这样做的延迟很糟糕,并且需要大量重复性工作.因此,我们在后台进行这项工作,您 运行 您的查询不是针对事件存储“现在”的样子,而是针对事件存储在最近报告的检查点时的样子。