Skip to main content

Realtionship

By Reference(Normalization)

  • Easier to maintain data consistency
  • Only need to update 1 document if value changes
let author = {
_id:"11223344",
name:"James Peterson"
}
let course = {
_id:"55667788",
title:"Intro to Javascript",
authors:["11223344"]
}

By Embedded(Denormalization)

  • Faster performance
  • Need to Update all related documents when value changes
let course = {
_id:"55667788",
title:"Intro to Javascript",
authors:[{_id:"11223344",name:"James Peterson"}]
}

Hybrid

  • Snapshot of data at a point in time
  • e.g. an order has price of product at that time
let author = {
_id:"11223344",
name:"James Peterson",
DOB:"1980-10-12",
...other properties
}
let course = {
_id:"55667788",
title:"Intro to Javascript",
authors:[{_id:"11223344",name:"James Peterson"}]
}

Modeling by Reference

const authorSchema = new mongoose.Schema({
name:String,
bio:String,
website:String
});
const Author = new mongoose.model('Author',authorSchema);
const courseSchema = new mongoose.Schema({
title:String,
author:{type:mongoose.Schema.Types.ObjectId,ref:'Author'} //this references the author document by its _id
});
const Course = mongoose.model('Course',courseSchema);

Populate method

  • reference documents in other collections
const listCourses = async () =>{
const courses = await Course.find().populate('author') //mongoose will get all the author details using the objectId
res.send(result);
}

const listCourses = async () =>{
const result = await Course.find().populate('author', 'name') //mongoose will only get author name
res.send(result);
}

Modeling by Embedded

const authorSchema = new mongoose.Schema({
name:String,
bio:String,
website:String
});
const Author = new mongoose.model('Author',authorSchema);
const courseSchema = new mongoose.Schema({
title:String,
author: authorSchema //this embeds the author inside courseSchema
});
const Course = mongoose.model('Course',courseSchema);

add array of subdocument

const Course = mongoose.model("course", new mongoose.Schema({
title:String,
authors:[authorSchema]
}));
const createCourse = async (title, authors) =>{
const course = new Course({title,authors});
const result = await course.save();
console.log(result);
}
createCourse("NodeJS Course", [new Author({name:"Peter"}),new Author({name:"James"})]);

const addAuthor = async (courseId,author){
const course = await Course.findById(courseId);
course.authors.push(author);
course.save();
}
addAuthor("6234125asdf25c554werw87", new Author({name:"Janet"}));

remove subdocument

const removeAuthor = async (courseId,authorId){
const course = await Course.findById(courseId);
const author = course.authors.id(authorId);
author.deleteOne();
course.save();
}
removeAuthor("6234125asdf25c554","2348794j78678sd78");

remove subdocument directly in database

const removeAuthor = async (courseId){
const course = await Course.update(_id:courseId,{
$unset:{'author':''}
});
}
removeAuthor("6234125asdf25c554");

update subdocument

const updateAuthor = async (courseId,newName){
const course = await Course.findById(courseId);
course.author.name = newName;
course.save();
}
updateAuthor("6234125asdf25c554","James McGill");
update subdocument directly in database
const updateAuthor = async (courseId,newName){
const course = await Course.update(_id:courseId,{
$set:{'author.name':newName}
});
}
updateAuthor("6234125asdf25c554","James McGill");