文档数据库:冗余数据,引用等(MongoDB专门)

时间:2010-10-18 05:21:44

标签: mongodb document-database

似乎我遇到了许多情况,其中构建我的数据的适当方法是将其拆分为两个文档。让我们说这是一个连锁商店,你节省了每个客户访问过的商店。商店和客户需要是独立的数据,因为它们与许多其他东西相互作用,但我们确实需要将它们联系起来。

因此,简单的答案是将用户的Id存储在商店文档中,或将商店的Id存储在用户的文档中。但很多时候,您希望访问1-2个其他数据用于显示目的,因为Id无用。就像客户名称或商店名称一样。

  1. 您通常会存储整个文档的副本吗?或者只是存储您需要的数据?可能取决于文档的大小与您需要的大小。
  2. 您如何处理重复数据的事实?当数据发生变化时,你会去搜索数据吗?加载后的某个时间间隔更新数据?只有在你能负担得起陈旧数据时才重复?
  3. 非常感谢您对任何“最佳做法”的投入和/或链接,或至少对这些主题进行了充分理性的讨论。

3 个答案:

答案 0 :(得分:29)

基本上有两种情况:新鲜陈旧

新鲜数据

存储重复数据很容易。维护重复数据是困难的部分。因此,最简单的方法是避免维护,只需不要存储任何重复数据。如果您需要新数据,这主要非常有用。仅存储引用,并在需要检索信息时查询集合。

在这种情况下,由于额外的查询,您将有一些开销。另一种方法是跟踪重复数据的所有位置,并更新每次更新的所有实例。这也涉及开销,特别是在您提到的N-to-M关系中。无论哪种方式,如果您需要新数据,有一些开销。你不可能两全其美。

陈旧数据

如果您能负担得起陈旧数据,事情会变得容易多了。为避免查询开销,您可以存储重复数据。为避免必须维护重复数据,您不会存储重复数据。至少不是主动

在这种情况下,您还希望仅存储文档之间的引用。然后使用周期性map-reduce作业生成重复数据。然后,您可以查询单个map-reduce结果,而不是单独的集合。这样可以避免查询开销,但您也不必搜索数据更改。

摘要

仅存储对其他文档的引用。如果您能负担过时的数据,请使用定期的map-reduce作业来生成重复数据。避免维护重复数据;这很复杂且容易出错。

答案 1 :(得分:14)

这里的答案实际上取决于您对数据的最新需求。

@Niels 在这里有一个很好的总结,但我认为你可以“作弊”是公平的。

假设您要显示用户使用的商店。这里显而易见的问题是你无法将商店“嵌入”用户b / c商店本身太重要了。但是你可以做的是在用户中嵌入一些存储数据。

只需使用您想要显示的内容,例如“商店名称”。所以你的User对象看起来像这样:

{
  _id : MongoID(),
  name : "Testy Tester",
  stores : [ 
             { _id : MongoID(), "name" : 'Safeway' },
             { _id : MongoID(), "name" : 'Walmart' },
             { _id : MongoID(), "name" : 'Best Buy' }
            ]
}

这样您就可以显示典型的“网格”视图,但需要一个链接来获取有关商店的更多数据。

答案 2 :(得分:2)

回答您的直接问题:

  1. 没有重复。
  2. 没有重复。
  3. 您应该拥有的唯一重复项是“简单”值,例如权重(可能恰好相同,但在单独存储的时间或空间中效率不高),并且ID引用另一个对象(是重复的值,但比它们替换的重复对象数据小得多且易于管理。

    现在,回答你的情景:你想要的是多对多关系。这里通常的解决方案是制作第三个“通过”或“桥接”表/集合,可能称为StoreUsers:

    StoreUsers
    ----------
    storeuser_id
    store_id
    user_id
    

    您可以为商店和用户之间的每个链接添加一条记录,无论是针对不同的商店,不同的用户还是一个商店中的一堆用户。然后,您可以单独查看此内容,无论是商店还是用户。 MongoDB也提倡这种方法;它不是特定于RDBMS的。