I have an List document with embedded Comments. Along with the user’s comment in the view, I’d like to display their screen name and profile picture. The profile picture could change and so could the screen name.
I’m trying to determine what the best practice is here for design. To best leverage Mongo, it seems like like the embedded Comment should look like the following:
Comment Model
class Comment
include Mongoid::Document
field :user_id
field :username
field :profile_pic_url
field :content
field :created_at, type: Date
embedded_in :list, :inverse_of => :comments
end
The risk though is that comment data (user’s screen name and profile pic) becomes stale if the user changes them unless there’s a after_save filter on the User model for instance that looks to update all instances in comments.
Any guidance on proper design? I could make it so that comments are not embedded and make it so that a user has many comments and a list has many comments, but I’m trying to play to Mongo’s strengths.
Your application, it’s access patterns, scaling, and performance requirements trump backend issues. With SQL, normalization and linking/referencing is pretty much your only choice, but with MongoDB, you can embed.
MongoDB provides the flexibility to match schema to the needs of your application, you can choose normalization/linking/referencing or denormalizing/embedding as needed, and Mongoid makes it easy to choose.
(a) Normalization reduces redundancy, following the good principle of Don’t Repeat Yourself (DRY).
(b) Denormalization introduces redundancy, following common practices such as caching or memoizing for performance.
In general based on the needs of your application:
High consistency required – yes: normalize / link, no: denormalize / embed
High read performance required – yes: denormalize / embed, no: normalize / link
High write performance required – yes: normalize / link, no: denormalize / embed
High scaling required – yes: normalize / link, no: denormalize / embed
Relationships:
one-to-one – yes: denormalize / embed, no: …
one-to-many – yes: denormalize / embed, no: …
many-to-many – yes: normalize / link, no: …
There are various techniques for handling consistency, ex., background or nightly process for eventual consistency, look-aside cache for immediate consistency, etc.
The bad news is that there’s no formula that requires no thought. The good news is that MongoDB has the flexibility to match your application. 10gen offers talks on Schema Design.