代码之家  ›  专栏  ›  技术社区  ›  Alexander Finn

MongoDB中的模拟关系

  •  22
  • Alexander Finn  · 技术社区  · 16 年前

    MongoDB是最流行的NoSQL解决方案之一,它具有这种方法的大部分优点。但我仍在努力解决的一个问题是如何反映NoSQL数据存储中的对象关系,特别是MongoDB。

    例如,让我们考虑一个简单的数据模型:用户、文章和注释。我很清楚,评论本身没有价值,因此成为了文章的嵌入对象。但当涉及到用户时——这变得很棘手,因为用户本身就是一个实体,而不是与post结合在一起。现在,如果我需要在网页上列出带有用户名和指向配置文件的链接的文章,我需要一个关于文章作者(至少是姓名和ID)的文章和信息列表。

    我在这里看到了两个可能的解决方案:

    1. 以每个日志条目包含其作者ID和全名(以及在列出日志时可能需要的任何其他用户属性)的方式对数据进行非规范化。通过这种方式,我可以使对数据的查询变得非常简单,但是当用户更新他/她的配置文件时,我也需要更新用户发布的所有文章。但是我还需要将用户属性存储在comments对象中,这意味着更新用户配置文件实质上需要我更新用户至少有一条注释的所有文章,除非我想将注释存储在单独的集合中。
    2. 只在Post对象中存储用户ID并运行2个查询:一个用于获取文章列表,另一个用于获取用户ID位于文章作者列表中的用户列表。这需要在我的应用程序代码中进行2次查询和额外的处理,以将用户映射到日志。

    我确信我不是第一个面临这个问题的人,但不幸的是,到目前为止我还没有找到任何关于这个问题的最佳实践。意见?

    2 回复  |  直到 9 年前
        1
  •  14
  •   TTT    16 年前

    这两个都是有效的解决方案,解决方案1的优点是,您只需从数据库中检索一个文档,就可以显示这样的页面。用户不经常更新他们的配置文件,您可以在用户配置文件更改后异步更新所有文章和嵌入的注释。您可以为用户id上的文章和嵌入的注释编制索引,这样更新应该很快。MongoDB中的更新速度非常快,因为MongoDB进行了适当的更新,并且您不能回滚或提交,所以MongoDB不必记录更改。

    然而,像stackoverflow这样的网站上的用户也有声誉,这种声誉的变化比他们的个人资料要大得多。

    解决方案2要求每页检索更多的文档,但是您可以将$in运算符与userid(post的userid+comments的userid)列表一起使用,因此您只需要两个“selects语句”。

        2
  •  1
  •   user193116    16 年前

    我也遇到了类似的问题,我就是这样解决的:

    (当我解决这个问题时,我的驾驶动机是避免加入)

    使用两个单独的集合:一个用于用户,一个用于文章。将用户对象与日志一起存储在“日志”集合中。更改用户对象时不要更新posts集合。维护用户信息是用户的集合。当然,post数据最终会包含过时的用户信息,但用户更改其配置文件的频率如何。

    如果必须显示绝对最新的用户信息以及每个帖子,那么从缓存中检索用户信息。

    希望这对你有用。我的解决方案仍在开发中,因此我没有要与您共享的负载测试结果。