zdixon
zdixon

Reputation: 349

MeteorJS + MongoDB: How should I set up my collections when users can have the same document?

I wasn't quite sure how to word my question in one line, but here's a more in depth description.

I'm building a Meteor app where users can "own" the same document. For example, a user has a list of movies they own, which of course multiple people can own the same movie. There are several ways I've thought of structuring my database/collections for this, but I'm not sure which would be best.

I should also note that the movie info comes from an external API, that I'm currently storing into my own database as people find them in my app to speed up the next lookup.

Option 1 (My current config): One collection (Movies) that stores all the movies and their info. Another collection that basically stores a list of movie ids in each document based on userId. On startup, I get the list of ids, find the movies in my database, and store them in local collections (there are 3 of them). The benefit that I see from this is I only have to store the movie once. The downside that I've ran into so far is difficulty in keeping things in sync and properly loading on startup (waiting on the local collections to populate).

Option 2 : A Movies collection that stores a list of movie objects for each user. This makes the initial lookup and updating very simple, but it means I'll be storing the same fairly large documents multiple times.

Option 3: A Movies collection with an array of userids on each movie that own that movie. This sounds pretty good too, but when I update the movie with new info, will an upsert work and keep the userids safe?

Upvotes: 3

Views: 117

Answers (1)

MarkWheeler
MarkWheeler

Reputation: 70

Option 3 seems sensible. Some of the choice may depend on the scale of each collection or the amount of links (will many users own the same movie, will users own many movies).

Some helpful code snippits for using option 3:

Upsert a movie detail (does not affect any other fields on the document if it already exists):

Movies.upsert({name: "Jaws"}, {$set: {year: 1975}});

Set that a user owns a movie (also does not affect any other document fields. $addToSet will not add the value twice if it is already in the array while using $push instead would create duplicates):

Movies.update({_id: ~~some movie id~~}, {$addToSet: {userIds: ~~some user id~~}});

Set that a user no longer owns a movie:

Movies.update({_id: ~~some movie id~~}, {$pull: {userIds: ~~some user id~~}});

Find all movies that a user owns (mongo automatically searches the field's array value):

Movies.find({userIds: ~~some user id~~});

Find all movies that a user owns, but exclude the users field from the result (keep the document small in the case that movie.userIds is a large array or protect the privacy of other user-movie ownership):

Movies.find({userIds: ~~some user id~~}, {userIds: 0});

Upvotes: 1

Related Questions