Document Databases: Redundant data, references, etc. (MongoDB specifically) Document Databases: Redundant data, references, etc. (MongoDB specifically) mongodb mongodb

Document Databases: Redundant data, references, etc. (MongoDB specifically)


There are basically two scenario's: fresh and stale.

Fresh data

Storing duplicate data is easy. Maintaining the duplicate data is the hard part. So the easiest thing to do is to avoid maintenance, by simply not storing any duplicate data to begin with. This is mainly useful if you need fresh data. Only store the references, and query the collections when you need to retrieve information.

In this scenario, you'll have some overhead due to the extra queries. The alternative is to track all locations of duplicate data, and update all instances on each update. This also involves overhead, especially in N-to-M relations like the one you mentioned. So either way, you will have some overhead, if you require fresh data. You can't have the best of both worlds.

Stale data

If you can afford to have stale data, things get a lot easier. To avoid query overhead, you can store duplicate data. To avoid having to maintain duplicate data, you're not going to store duplicate data. At least not actively.

In this scenario you'll also want to store only the references between documents. Then use a periodic map-reduce job to generate the duplicate data. You can then query the single map-reduce result, rather than separate collections. This way you avoid the query overhead, but you also don't have to hunt down data changes.

Summary

Only store references to other documents. If you can afford stale data, use periodic map-reduce jobs to generate duplicate data. Avoid maintaining duplicate data; it's complex and error-prone.


The answer here really depends on how current you need your data to be.

@Niels has a good summary here, but I think it's fair to note that you can "cheat".

Let's say that you want to display the Stores used by a User. The obvious problem here is that you can't "embed" the Store inside the User b/c the Store is too important on its own. But what you can do is embed some Store data in the User.

Just use the stuff you want for display like "Store Name". So your User object would look like this:

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

This way you can display the typical "grid" view, but require a link to get more data about the store.


To answer your direct questions:

  1. No duplicates.
  2. No duplicates.

;)

The only duplicates you should ever have are "simple" values like weights (which may happen to be the same, but aren't any more efficient in either time or space to store separately), and ids referencing another object (which are duplicate values, but much smaller and more manageable than the duplicate object data they replace).

Now, to answer your scenario: what you want is a Many-to-Many relationship. The usual solution here is to make a third "through" or "bridge" table/collection, probably called StoreUsers:

StoreUsers----------storeuser_idstore_iduser_id

You add a record to this for each link between stores and users, whether it's for a different store, a different user, or a bunch of users in one store. You can then look this up independently, for either the Store, or the User. MongoDB advocates this approach too; it's not RDBMS-specific.