Relationships in Mongo

Learning Objectives

Objectives
Describe one-to-one, one-to-many, and many-to-many data relationships
Write mongoose schemas for referenced and embedded data
Build the appropriate queries for nested data relationships

Types of Data Relationships

One-to-One

Each person "has one" social security number, and each social security number "has one" person.

one to one erd

One-to-Many

Each tree "has many" leaves, and each leaf "has one" tree.

one to many erd

Many-to-Many

Each student "has many" classes, and each class "has many" students.

many to many erd

Entity Relationship Diagrams

Entity relationship diagrams (ERDs) represent the relationships between data or entities.

Entity Relationship Diagram example

Note: Attributes can be represented as line items under a heading (like all of the Item1, Item2, Item3 under each heading above) or as ovals stemming from the heading's rectangle.

More guidelines for ERDs

Data Relationships with Mongoose

Embedded Data

  • Embedded Data is directly nested inside of other data. Each record has a copy of the data.

Referenced Data

  • Referenced Data is stored as an id inside other data. The id can be used to look up the information. All records that reference the same data look up the same copy.

There are tradeoffs between efficiency and consistency depending on which one you choose.

Scenario:

How would you design the following?

  • A User that has many Tweets?
  • A Food that has many Ingredients?

Implementing each

Referencing Data

var foodSchema = new Schema({
  name: {
    type: String,
    default: ""
  },
  ingredients: [{
    type: Schema.Types.ObjectId,  //REFERENCING :D
    ref: 'Ingredient'
  }]
});

var ingredientSchema = new Schema({
  title: {
    type: String,
    default: ""
  },
  origin: {
    type: String,
    default: ""
  }
});

Embedding Data

var tweetSchema = new Schema({
  body: {
    type: String,
    default: ""
  }
});

var userSchema = new Schema({
  username: {
    type: String,
    default: ""
  },
  tweets: [tweetSchema]   // EMBEDDING :D
});

Route Design

Remember RESTful routing? It's the most popular modern convention for designing resource paths for nested data. Here is an example of an application that has routes for Store and Item models:

RESTful Routing

HTTP Verb Path Description
GET /store Get all stores
POST /store Create a store
GET /store/:id Get a store
DELETE /store/:id Delete a store
GET /store/:store_id/items Get all items from a store
POST /store/:store_id/items Create an item for a store
GET /store/:store_id/items/:item_id Get an item from a store
DELETE /store/:store_id/items/:item_id Delete an item from a store

In routes, avoid nesting resources more than one level deep.

Challenges

Create and navigate through relational data in MongoDB.

Goal: start up a node REPL with access to our database

  1. Start mongoDB with mongod.

  2. In another tab, git clone the w4_d2_1_exercise repo, and cd into the new w4_d2_1_exercise directory.

  3. cd into the folder exercise.

  4. Take a quick look at console.js, a script we wrote to help set up your REPL to use your database. Don't worry about exactly how it works, but notice this line:

    var db = require("./models");
    

    Hint: in the REPL, all your models will be inside an object called db.

  5. Type node console.js in the terminal to enter a REPL where you can interact with your database.

Goal: inspect and understand existing code base

  1. You're working from existing code here, so start by figuring it out. Open models.js in Sublime.

  2. models.js has many comment lines that currently just ask questions (cmd+f ? to find them all). Replace these lines with a VERY brief answer to their questions.

  3. Stretch: Draw an entity relationship diagram for Users and Tweets.

  4. Stretch: Draw an entity relationship diagram for Foods and Ingredients.

Goal: manipulate embedded data

NOTE: After each step is successful, save the code you used in challenges.js.

  1. In the REPL, create a user.

  2. Create at least two tweets.

  3. Embedded the tweets you created into the user.

  4. List all the users.

  5. List all tweets of a specific user.

Goal: manipulate referenced data

NOTE: After each step is successful, save the code you used in challenges.js.

  1. Create at least two ingredients.

  2. Create a food that references those ingredients.

  3. List all the foods.

  4. List all the ingredients in the food you created. Hint: see the story/creator example in the mongoose populate documentation.