如何更新与另一个聚合有关联的聚合的ReadModel

问题描述

我正在尝试分离读写模型。总之,我有这两个实体,它们之间有关联:

//AgregateRoot
class ProfessionalFamily {
    private ProfessionalFamilyId id;
    private String name;
}

//AgregateRoot
class Group {
    private GroupId id;
    private String literal;
    private ProfessionalFamilyId professionalFamilyId; //ManyToOne association referenced by the ID of "professional-family"
}

一个是我用来在Grid中返回数据的读取模型。

class GroupReadModel {
    private String id;
    private String groupLiteral;
    private String professionalFamilyName;
}

我想对NoModel进行ReadModel查询,并将它们分开用于写模型。但令我头疼的是:使用这种方法,在创建组时,我会触发一个事件(GroupCreated),并且一个事件处理程序会监听该事件,并将读取/查看/投影模型存储在Nosql数据库中。所以我的问题是:如果我需要更新ProfessionalFamilyName且与例如1000个以上的组相关(还有更多的组),我如何更新ReadModel中与我拥有的ProfessionalFamily相关的所有Groups更新了吗?很有可能我做得不好。

非常感谢。

解决方法

NoSql数据库通常不设计为支持数据规范化,甚至有意破坏此概念。如果要使用关系数据库系统,通常会规范化数据并将其归入每个组,而只存储ProfessionalFamily的ID,而不是在每个组文档中复制ProfessionalFamily的名称。因此,通常来说,对于NoSql数据库复制是可接受的。

但是我认为在决定使用NoSql或关系数据库之前,您应该考虑(至少)以下几点:


读写速度的优先级

如果您需要快速进行写入(在您的情况下为名称更改),因为它们经常发生并且读取速度较低,那么NoSql并不是最佳选择。您仍然可以研究诸如MongoDB之类的技术,该技术提供了某种混合方法,并允许在一定程度上对数据进行规范化和索引。

在关系数据库中具有标准化结构时,写入通常会更快,而在NoSql数据库中不进行标准化和重复的情况下,读取通常会更快。但这当然取决于您正在比较的现有技术以及我们正在讨论的实体(在您的情况下是“组”)的数量以及交叉引用数据的数量。如果由于规范化而需要在读取期间进行大量联接,则与所有由于重复而已存在所有必需数据的Group文档相比,读取性能通常会更差。


控制数据结构/模式

如果您是知道数据外观的人,则可能不需要NoSql数据库的优势,该数据库非常适合经常更改或不受您控制的数据结构。如果情况并非如此,您可能无法从NoSql技术中受益匪浅。


此外,还需要考虑另一件事: 读取的模型数据必须保持多大的一致性 ?当您采用某种事件来源方法时,我想您已经开始采用最终一致性了。这意味着不仅事件处理是异步执行的,而且您还可以接受-回到您的示例-并非所有组都同时使用新的家族名称进行更新,而且异步或通过某些后台作业进行更新(如果是)一个组仍然显示旧名称,而另一些组已经显示新名称已有一段时间了。


很可能我做得不好。

只要您出于正确的理由(包括这些考虑因素)决定选择NoSql(或反对),您选择这种方法就不会做任何错误或正确的事情。

,

我和我的团队最近讨论了类似的情况,我们通过将CRUD方法更改为DDD方法来解决了该问题。这是一个示例:

为旅行者提供访问目的地的列表。

如果我遇到诸如 ID DeletedPersonID ProductKey PartyID PartyName SubPartyID 9 461 17 34 ABC 33 10 95 17 34 XYZ null 这样的事件,那么我应该像您所说的那样遍历每一个旅行者,但这有意义吗?从用户的角度来看,destinationUpdated是什么意思?没有!您应该找到真正的用户意图。

如果旅行者输入错误时访问了目的地,那么您的事件应该是destinationUpdated,这可以解决问题,因为travelerCorrectedDestination现在包含旅行者ID,因此您不必再遍历所有旅行者

通过采用DDD方法,问题通常可以自行解决。