Model Relations#

Relations are logical links which define how models are connected with each other. A document of a model can be connected to one or more documents of the same or another model.

A relation between models are generally of two types:

  • Belongs To: A document in the source model is connected with a document in the destination model by putting the id of the destination document in the source document.
  • Has Many / Has One: A document in the source model is connected with one or many documents in destination models by putting the id of the source document in destination document(s).

Relation: Belongs To#

Example#

A blog post belongs to a user

User Schema#

{
    name: {
        type: String,
        required: true
    }
}

Blog Post Schema#

{
    name: {
        type: String,
        required: true
    },
    author: {
        type: Schema.Types.ObjectId,
        ref: 'User',
        required: true
    }
}

Populate#

Now the author of a blog post can be easily populated by:

Post.find({}).populate('author')

/*
  {
    _id: 5f71af94e66f4728f68ffc06,
    name: 'Relation: Belongs To',
    author: {
      _id: 5f71af94e66f4728f68ffc05,
      name: 'abskmj',
      email: 'abskmj@email.com'
    }
  }
*/

Relation: Has Many / Has One#

Example#

A user has many blog posts

User Schema#

schema.virtual('posts', {
    ref: 'Post',
    localField: '_id',
    foreignField: 'author'
})

Populate#

Now the author of a blog post can be easily populated by:

User.find({}).populate('posts')

/*
  {
    _id: 5f71ce43687f2a2fb97fa462,
    name: 'abskmj',
    email: 'abskmj@email.com',
    posts: [
      {
        _id: 5f71ce43687f2a2fb97fa463,
        name: 'Relation: Belongs To',
        author: 5f71ce43687f2a2fb97fa462
      },
      {
        _id: 5f71ce43687f2a2fb97fa464,
        name: 'Relation: Has One',
        author: 5f71ce43687f2a2fb97fa462
      }
    ],
    id: '5f71ce43687f2a2fb97fa462'
  }
*/

Note#

Virtuals are not included in string version of the model instances by default. To include them, set the virtuals option to true on schema’s toObject and toJSON options.

const User = new Schema(userSchema, {
    toObject: { virtuals: true }, 
    toJSON: { virtuals: true } 
})

A working codebase for reference is available at gist.github.com

Reference#