我正在尝试使用MongoDB,C#和NoRM来处理一些示例项目,但是在这一点上,我在围绕数据模型时遇到了困难。使用RDBMS的相关数据是没有问题的。然而,在MongoDB中,我很难决定如何处理它们。
让我们以StackOverflow为例......我可以理解问题页面上的大部分数据都应该包含在一个文档中。标题,问题文本,修订,评论......在一个文档对象中都很好。
我开始变得朦胧的地方是关于用户数据的问题,例如用户名,头像,声誉(特别经常变化)...你是否每次都有非规范化和更新成千上万的文档记录是用户更改还是以某种方式将数据链接在一起?
在不导致每次页面加载时发生大量查询的情况下,实现用户关系的最有效方法是什么?我注意到NoRM中的DbReference<T>
类型,但尚未找到使用它的好方法。如果我有可空的可选关系怎么办?
感谢您的见解!
答案 0 :(得分:2)
我发现的余额是使用SQL作为规范化数据库而使用Mongo作为非规范化副本。我使用ESB使它们彼此保持同步。我使用的概念称为“准备好的文档”和“存储的文档”。存储的文档是仅保存在mongo中的数据。对于非关系数据非常有用。准备好的文档包含可以使用规范化数据库中的数据重建的数据。它们在某种程度上充当活动缓存 - 如果数据不同步,它们可以从头开始重建(在复杂的文档中,这是一个昂贵的过程,因为这些文档需要重建许多查询)。它们也可以一次更新一个字段。这就是服务总线的用武之地。它响应了规范化数据库更新后发送的事件,然后更新相关的mongo准备文件。
使用每个数据库的优势。允许SQL成为确保数据完整性的写入数据库。让Mongo成为一个快速且只能包含子文档的只读数据库,这样您就可以减少查询次数。
**编辑** 我只是重新阅读你的问题并意识到你实际要求的是什么。我将离开原来的答案,以防它有用。
我处理Stackoverflow示例的方法是在每个注释中存储用户ID。你会加载一个包含所有评论的帖子。这是一个查询。
然后,您将遍历注释数据并提取需要加载的用户ID数组。然后将它们作为批处理查询加载(使用Q.In()查询运算符)。总共有两个查询。然后,您需要将数据合并为最终形式。您需要在何时执行此操作以及何时使用类似ESB的操作来手动更新每个文档。使用最适合您的数据结构的每个场景的方法。
答案 1 :(得分:1)
为什么要避免非规范化并更新“数千个文档记录”? Mongodb db专为非规范化而设计。 Stackoverlow在后台处理数百万种不同的数据。有些数据可能会在短时间内过时,而且没关系。
上面说的主要思想是你应该使用非规范化文档,以便在ui快速显示它们。
您不能通过引用文档进行查询,无论如何都需要非规范化。
我还建议您查看cqrs架构。
答案 2 :(得分:1)
尝试调查cqrs and event sourcing架构。这将允许您按队列更新所有这些数据。
答案 3 :(得分:1)
我认为你需要取得平衡。
如果我是你,我只会在每篇帖子中引用用户ID而不是他们的名字/声誉。
与RDBMS不同,您可以选择在文档中嵌入注释。