问题描述
我正在尝试分离读写模型。总之,我有这两个实体,它们之间有关联:
//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方法,问题通常可以自行解决。