0

我有 mysql 的知识,但我正在尝试学习/理解 mongodb,到目前为止我遇到的问题是非关系数据库的想法。没有加入,这有点麻烦(但我明白为什么)。我希望您回答我的是以下问题的解决方案:

假设我们有帖子和评论。我们在 mongodb 中创建了两个对象,如果我们想显示某个用户对某个帖子的评论,我们只需查询每个对象,然后按 id 组合表。我不明白的是,如果已经评论过几个帖子的用户更改了他的昵称会发生什么。那么我们将如何解决这个问题。我是否必须更改用户曾经评论过的所有帖子和评论?

数据库架构:

POSTS
    text
    id

COMMENT
    text
    post_id
    author_name
4

3 回答 3

3

首先,我认为您提出了正确的问题。您是对的,作为一个非关系型数据库,MongoDB 不会为您管理参照完整性问题。如果确实存在引用完整性问题,这可能会让人有些头疼,因为如果您的某个用户修改了您的一条信息,您会发现自己处于可能需要更新大量文档的情况'已存储在您的所有文档中。让我们以你的例子为例,除了翻译成我通常期望的第一次尝试如何在 MongoDB 上设置它......

db.posts.save({
    author:"susan@yahoo.com",
    name:"Susan Person",
    text:"This is my first post. Isn't it fancy?",
    comments:[
         { author:"john@google.com", name:"John", text:"What a great post!" },
         { author:"sally@email.com", name:"Sally", text:"You really put some thought into this." }
    ]
});

db.authors.save({
    _id:"susan@yahoo.com",
    name:"Susan Person",
    favorite_icecream:"Chocolate",
});

我比你的例子更充实了一些东西,但我希望这能帮助你明白我要说什么。

所以。在没有听起来过于禅宗的情况下,我认为回答您问题的唯一方法是问另一个问题:您真的需要用新昵称更新所有现有评论吗?

根据我的经验,答案可能是否定的。但是,如果帖子的原作者(在这种情况下是苏珊)更改了他们的用户名,您可能想要这样做。那么你是怎么做到的呢?您首先修改作者文档,然后选择所有带有 { author:"susan@yahoo.com" } 的文档并更新这些帖子的作者。

使用您的经验和您对系统将如何使用的知识决定您的架构。如果您确实需要确保评论的名称反映作者集合中的条目,那么您还必须为所有这些条目做额外的工作。

您的问题还有一些更高级的解决方案。例如,您可能决定需要快速访问帖子的前 10 条评论,然后您可以让用户等待,同时将其余评论从数据库中异步拉出并进行相关匹配将数据拉到一起。在这种情况下,您的架构看起来与上述类似,但您不会存储超过 10 条评论,并将名称复制到帖子上,您可能会将所有剩余评论存储在仅引用用户的附加集合中电子邮件。然后,当您去查找评论时,您可以对用户集合中的电子邮件进行第二次查询,并确保您获得最新的名称。随着时间的推移,评论会滚动,

有关您可能想要选择的不同选项的更详细比较,请参阅以下链接:

http://www.alvinonmongodb.com/2012/07/schema-design-3-embedding-versus.html

正如文章作者所说:

问题并不是真正的嵌入或链接,而应该是“我的用例和访问模式是什么”。如果你知道这一点,那么嵌入、链接或混合模型的决定就更容易做出了。

于 2012-11-27T13:10:50.577 回答
2

有不同的方法可以实现您想要的:

  • 使用 _id 代替名称:这与 SQL 中的外键几乎相同,但您没有任何检查相关对象是否存在等等。当然,如果要显示用户名,则必须查询每个用户名。使用这意味着开销,但如果您的 MongoDB 上的负载不高,则应该不会太多。更好的是,根据你有多少用户,你可以在 id 和 username 上建立一个索引,这样用户名就保留在 RAM 中,这意味着读取速度很快。

  • 更新所有评论:您可以在重命名后更新某个用户名的所有评论。为此,您可能希望将 user_id 存储在评论集合中的用户名旁边,然后查询 id 并更改用户名。我猜 MongoDB 有办法快速做到这一点。

  • 使用嵌入式集合:MongoDB 中有嵌入式集合,可以解决其中一些问题并创建其他问题。您不想在评论中嵌入用户,但对于其他用例,这非常方便。我只是在这里提一下。

使用 MongoDB

总体问题是,在使用 NoSQL 数据库时,您必须考虑您的用例。不是“我们规范化我们的数据,然后看看我们如何编写查询”,而是“我们想这样那样使用数据,我们需要如何存储数据”。因此,从上述情况来看,可能还有其他更方便的解决方案。

也许它使用了一个特殊的 id 和前面的用户名(记住,id 可以是任何东西),然后使用应用程序来提取用户名。或者,它可能会保留某种合并文档的重复集合,其中评论和用户信息一起存储在他们自己的集合旁边,如果发生变化,可以重新生成。

习惯这种工作方式需要一些时间,但你会习惯的。如果您刚刚开始,您可能不会开发一个每秒点击 100000 次的平台,因此您可以只存储对象 id 并在需要时对该 id 进行第二次查询以获取用户名。

于 2012-11-27T12:12:21.043 回答
0

即使它是一个关系数据库,也不是一个很好的模式。您将在评论文档中使用 author_id 而不是 author_name。该 ID 对于该用户来说是唯一的。然后创建一个关联 author_name 和 author_id 的用户文档。

现在,当您更改作者时,它只会发生在一个文档中。

于 2012-11-27T12:00:59.973 回答