2

我想我理解 ES + CQRS 上下文中读取模型的想法(如果不是,请纠正我)。但是,我仍然对在“严肃”报道的背景下使用它有一些疑问。假设我使用关系数据库和一些 ORM 来处理我的读取模型。一个基本的“汇总统计读取模型”可能如下所示:

 class SummaryStats1
    {
    public Guid TypeId { get; set; }
    public string TypeName { get; set; }
    public Guid SubTypeId { get; set; }
    public string SubTypeName { get; set; }
    public int Count { get; set; }
    }

给定一个事件:

TypeId = 3acf7d6f-4565-4672-985d-a748b7706a3e
TypeName = Bla1
SubTypeId = 41532aa1-f5d1-4ec4-896b-807ad66f75fc
SubTypeName = Bla2

规范化器将:

(1) 检查是否存在上述组合的实例(由 TypeId、TypeName、SubTypeId、SubTypeName 定义) (2) 如果没有实例,则创建实例并将 Count 设置为 1。如果有它会将计数增加一。

这是可接受的报告方法吗?我想人们可以针对这种非规范化的数据结构(用于过滤和其他 sql 'projections')运行非常有效的选择:

SELECT  TypeName, Sum(Count) FROM SummaryStats1 GROUP BY TypeName

CQRS/ES 专家会同意这一点吗?这是做事的“方式”(即创建这些专用的报告阅读模型)吗?非常感谢对源代码/真实示例的任何引用。

4

1 回答 1

6

这是可接受的报告方法吗?

当然,是否是报告方法取决于您的要求,但总体思路是正确的。

总之:

您根据来自您的域的事件生成读取模型(有时使用的官方术语是Eager Read Derivation )。

读取模型可以是您想要的任何东西(sql、redis、mongo 等)。任何使您的查询高效的东西。例如,在您的示例中,您没有理由不能使用 2 个读取模型来更有效地进行查询(尽管您所描述的对于大多数情况来说可能已经足够了):

  1. 您描述的 sql 视图
  2. 一个预先聚合的视图,typeName这样您就不必每次在查询时都进行分组(而是在规范器中计算分组)。

简而言之,如何构建阅读模型没有正确或错误的方法。美妙之处在于,您可以完全自由地以任何您想要的方式(基于您设想的查询模式和性能瓶颈)对您的读取模型进行建模,而无需考虑这些模型如何影响写入(仅仅是因为它们不会因为cqrs 拆分读取和写入)

将事件溯源与 CQRS 结合使用提供了更好的可能性,即创建新的读取模型并通过简单地从事件源重放过去的事件来用数据填充它们。

只是一些可能被视为数据“读取模型”的额外示例:

  • Redis的INCR视图(这是您似乎描述的替代方案)
  • 一个 Elasticsearch / Solr 搜索索引
  • 用于按键快速查找的 KV 存储/索引。

再次的想法是,这些“读取模型”/视图通过向它们推送更新事件(通常通过 pubsub)始终保持最新(最终一致)

要获得更好的阅读,请参阅此问题的答案和链接: Read side implementation methods using CQRS

于 2014-06-03T13:12:40.073 回答