10/ Data relationship with Mongo

One to Many relationship

Users table - Posts table (1 user can have more posts)

Many to Many

Movies table - Actors table (more than 1 actor in each movie) We need a third table: Movie_id - Actor_id

Using Mongo

One to Few

  • Embed data in the document
const userSchema = new mongoose.Schema({
    fisrtname: String,
    lastname: String,
    //address will be give an id by mongo
    //to disable the id:
    // _id: {id:false}
    address: [
        { 
          city: String, 
          address: String,
          state: {
              type: String,
              required: true 
              }
        }
    ]
})

One to Many

  • Create a separate model and store the ObjectId in the table
  • Create a farm that contains a list of products (using their ObjectIds):
const {Schema} = mongoose;

const farmSchema = new Schema({
  name: String,
  city: String,
  products: [
    {type: Schema.Types.ObjectId, ref: 'Product'}
  ]
})

const Farm = mongoose.model('Farm', farmSchema)


const makeFarm = async() => {
  const farm = new Farm({name: 'Fruit Belly', city: 'Guinda, CA'});
  await farm.save();
  console.log(farm)
}

makeFarm();

const addProduct = async()=>{
  const farm = await Farm.findOne({name: 'Fruit Belly'});
  const pera = await Product.findOne({name: 'Pera'});
  farm.products.push(pera);
  const melon = await Product.findOne({name: 'Melon'});
  farm.products.push(melon);

  farm.save();
}

addProduct();

Output:

{   "_id" : ObjectId("61d5a9bc88904bbe0c9b8cef"), 
    "name" : "Fruit Belly", 
    "city" : "Guinda, CA", 
    "products" : [ ObjectId("61d5a77b333943a74ff12755"), ObjectId("61d5a77b333943a74ff12756"), ObjectId("61d5a77b333943a74ff12755") ], 
    "__v" : 1 
}
  • To display the products value inside the array we need to use populate
Farm.findOne({name: 'Fruit Belly'})
.populate('products')
.then(farm => console.log(farm));

Output:

{
  _id: new ObjectId("61d5a9bc88904bbe0c9b8cef"),
  name: 'Fruit Belly',
  city: 'Guinda, CA',
  products: [
    {
      _id: new ObjectId("61d5a77b333943a74ff12755"),
      name: 'Melon',
      price: 4.99,
      category: 'fruit',
      __v: 0
    },
    {
      _id: new ObjectId("61d5a77b333943a74ff12756"),
      name: 'Pera',
      __v: 0
    }
  ],
        _id: new ObjectId("61d5a77b333943a74ff12755"),
      name: 'Melon',
      price: 4.99,
      category: 'fruit',
      __v: 0
    },
  __v: 1
}

One to Many (Thousands)

  • More efficient to store the parent id to the child (i.e. store the user into a tweet, than all the tweets into an user)
const userSchema = new Schema({
  username: String,
  age: Number
})

const tweetSchema = new Schema({
  text: String,
  likes: Number,
  user: {type: Schema.Types.ObjectId, ref: 'User' }
})

const User = mongoose.model('User', userSchema);
const Tweet = mongoose.model('Tweet',tweetSchema);

const makeTweets = async () =>{
  const u1 = new User({username: 'chichi', age:'39'})
  //const u1 = await User.findOne({name: 'chichi'});
  const tw1 = new Tweet({text:'my first tweet', likes: 22, user: u1});
  //const tw2 = new Tweet({text:'my second tweet', likes: 12, user: u1});
  u1.save();
  tw1.save();
  //tw2.save();
}

makeTweets();

const findTweets = async ()=>{
  const t = await Tweet.findOne({text: 'my first tweet'}).populate('user', 'username')//retrieve only the username
  console.log(t);
}

findTweets();
Written on January 4, 2022