[mongodb] MongoDB relationships: embed or reference?

I'm new to MongoDB--coming from a relational database background. I want to design a question structure with some comments, but I don't know which relationship to use for comments: embed or reference?

A question with some comments, like stackoverflow, would have a structure like this:

Question
    title = 'aaa'
    content = bbb'
    comments = ???

At first, I want to use embeded comments (I think embed is recommended in MongoDB), like this:

Question
    title = 'aaa'
    content = 'bbb'
    comments = [ { content = 'xxx', createdAt = 'yyy'}, 
                 { content = 'xxx', createdAt = 'yyy'}, 
                 { content = 'xxx', createdAt = 'yyy'} ]

It clear, but I'm worried about this case: If I want to edit a specified comment, how do I get its content and its question? There is no _id to let me find one, nor question_ref to let me find its question. (I'm so newbie, that I don't know if there's any way to do this without _id and question_ref.)

Do I have to use ref not embed? Then I have to create a new collection for comments?

This question is related to mongodb reference embed

The answer is


If I want to edit a specified comment, how to get its content and its question?

You can query by sub-document: db.question.find({'comments.content' : 'xxx'}).

This will return the whole Question document. To edit the specified comment, you then have to find the comment on the client, make the edit and save that back to the DB.

In general, if your document contains an array of objects, you'll find that those sub-objects will need to be modified client side.


I know this is quite old but if you are looking for the answer to the OP's question on how to return only specified comment, you can use the $ (query) operator like this:

db.question.update({'comments.content': 'xxx'}, {'comments.$': true})

Yes, we can use the reference in the document.To populate the another document just like sql i joins.In mongo db they dont have joins to mapping one to many relationship document.Instead that we can use populate to fulfill our scenario..

var mongoose = require('mongoose')
  , Schema = mongoose.Schema

var personSchema = Schema({
  _id     : Number,
  name    : String,
  age     : Number,
  stories : [{ type: Schema.Types.ObjectId, ref: 'Story' }]
});

var storySchema = Schema({
  _creator : { type: Number, ref: 'Person' },
  title    : String,
  fans     : [{ type: Number, ref: 'Person' }]
});

Population is the process of automatically replacing the specified paths in the document with document(s) from other collection(s). We may populate a single document, multiple documents, plain object, multiple plain objects, or all objects returned from a query. Let's look at some examples.

Better you can get more information please visit :http://mongoosejs.com/docs/populate.html


I came across this small presentation while researching this question on my own. I was surprised at how well it was laid out, both the info and the presentation of it.

http://openmymind.net/Multiple-Collections-Versus-Embedded-Documents

It summarized:

As a general rule, if you have a lot of [child documents] or if they are large, a separate collection might be best.

Smaller and/or fewer documents tend to be a natural fit for embedding.


Well, I'm a bit late but still would like to share my way of schema creation.

I have schemas for everything that can be described by a word, like you would do it in the classical OOP.

E.G.

  • Comment
  • Account
  • User
  • Blogpost
  • ...

Every schema can be saved as a Document or Subdocument, so I declare this for each schema.

Document:

  • Can be used as a reference. (E.g. the user made a comment -> comment has a "made by" reference to user)
  • Is a "Root" in you application. (E.g. the blogpost -> there is a page about the blogpost)

Subdocument:

  • Can only be used once / is never a reference. (E.g. Comment is saved in the blogpost)
  • Is never a "Root" in you application. (The comment just shows up in the blogpost page but the page is still about the blogpost)

Actually, I'm quite curious why nobody spoke about the UML specifications. A rule of thumb is that if you have an aggregation, then you should use references. But if it is a composition, then the coupling is stronger, and you should use embedded documents.

And you will quickly understand why it is logical. If an object can exist independently of the parent, then you will want to access it even if the parent doesn't exist. As you just can't embed it in a non-existing parent, you have to make it live in it's own data structure. And if a parent exist, just link them together by adding a ref of the object in the parent.

Don't really know what is the difference between the two relationships ? Here is a link explaining them: Aggregation vs Composition in UML


In general, embed is good if you have one-to-one or one-to-many relationships between entities, and reference is good if you have many-to-many relationships.


MongoDB gives freedom to be schema-less and this feature can result in pain in the long term if not thought or planned well,

There are 2 options either Embed or Reference. I will not go through definitions as the above answers have well defined them.

When embedding you should answer one question is your embedded document going to grow, if yes then how much (remember there is a limit of 16 MB per document) So if you have something like a comment on a post, what is the limit of comment count, if that post goes viral and people start adding comments. In such cases, reference could be a better option (but even reference can grow and reach 16 MB limit).

So how to balance it, the answer is a combination of different patterns, check these links, and create your own mix and match based on your use case.

https://www.mongodb.com/blog/post/building-with-patterns-a-summary

https://www.mongodb.com/blog/post/6-rules-of-thumb-for-mongodb-schema-design-part-1


If I want to edit a specified comment, how do I get its content and its question?

If you had kept track of the number of comments and the index of the comment you wanted to alter, you could use the dot operator (SO example).

You could do f.ex.

db.questions.update(
    {
        "title": "aaa"       
    }, 
    { 
        "comments.0.contents": "new text"
    }
)

(as another way to edit the comments inside the question)


Examples related to mongodb

Server Discovery And Monitoring engine is deprecated Avoid "current URL string parser is deprecated" warning by setting useNewUrlParser to true MongoNetworkError: failed to connect to server [localhost:27017] on first connect [MongoNetworkError: connect ECONNREFUSED 127.0.0.1:27017] Failed to auto-configure a DataSource: 'spring.datasource.url' is not specified Failed to start mongod.service: Unit mongod.service not found db.collection is not a function when using MongoClient v3.0 MongoError: connect ECONNREFUSED 127.0.0.1:27017 MongoDB: How To Delete All Records Of A Collection in MongoDB Shell? How to resolve Nodejs: Error: ENOENT: no such file or directory How to create a DB for MongoDB container on start up?

Examples related to reference

Method Call Chaining; returning a pointer vs a reference? When to create variables (memory management) Reference to non-static member function must be called Cannot find reference 'xxx' in __init__.py - Python / Pycharm c++ "Incomplete type not allowed" error accessing class reference information (Circular dependency with forward declaration) C++ initial value of reference to non-const must be an lvalue Dependent DLL is not getting copied to the build output folder in Visual Studio How to write to error log file in PHP How to reference Microsoft.Office.Interop.Excel dll? Linker Error C++ "undefined reference "

Examples related to embed

How to embed new Youtube's live video permanent URL? Properly embedding Youtube video into bootstrap 3.0 page How to embed a Google Drive folder in a website How to hide the bar at the top of "youtube" even when mouse hovers over it? How to embed PDF file with responsive width Shrink a YouTube video to responsive width How can I embed a YouTube video on GitHub wiki pages? Embedding a media player in a website using HTML How to embed a YouTube channel into a webpage Embed an External Page Without an Iframe?