/mongo-structured-data

[js, mongo, mongoose, relationships, databases]

Primary LanguageJavaScript

Structured Data in Mongo

Why is this important?

This workshop is important because:

Organizing stored data in a predictable way essential to making it useful and actionable when an application performs searches and queries to derive information for its users.

What are the objectives?

After this workshop, developers will be able to:

  • Gain a deeper understanding of Mongo's ability to handle data organization
  • Compare and contrast embedded & referenced data
  • Design routes for nested resources
  • Build the appropriate queries for nested relationships

Where should we be now?

Before this workshop, developers should already be able to:

  • CRUD data in Mongo
  • Use Mongoose to write a Schema

##Data Organization in Mongo

There are two ways to form relationships in a document-based database...

####Embedded Data

  • Embedded Data is a document directly nested inside of other data

Uniquely identifying information, address information, user-generated content.

####Referenced Data

  • Referenced Data contains an id of a document that can be found somewhere else

Memberships, relationships, shared content

There is generally a tradeoff between efficiency (embedded) and consistency (referenced) depending on which one you choose.

###Scenario:

For each situation would you use embedded or referenced data? Discuss with a partner and be prepared to explain why.

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

###Implementation with Mongoose

Tip: Noteworthy code lines are denoted with the comment: NOTE.

Referencing Data

var foodSchema = new Schema({
  name: {
    type: String,
    default: ""
  },
  ingredients: [{
    type: Schema.Types.ObjectId,  // NOTE: Referencing
    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]	  // NOTE: Embedding
});

##Route Design

In order to read & create nested data we need to design appropriate routes.

The most popular, modern convention is RESTful routing. Here is an example of an application that has routes for Store and an Item models:

####RESTful Routing

HTTP Verb Path Description
GET /stores Get all stores
POST /stores Create a store
GET /stores/:id Get a store
PUT/PATCH /stores/:id Update a store
DELETE /stores/:id Delete a store
GET /stores/:storeId/items Get all items from a store
POST /stores/:storeId/items Create an item for a store
GET /stores/:storeId/items/:itemId Get an item from a store
PUT/PATCH /stores/:storeId/items/:itemId Update an item from a store
DELETE /stores/:storeId/items/:itemId Delete an item from a store

In routes resources should not be nested more than one level deep

Note: These routes omit the commonly used #new and #edit actions, which is common if the server is rendering HTML instead of JSON.

##Queries Exercise

####Goal

Create and navigate through relational data in MongoDB

####Setup

  • startup mongoDB with mongod
  • cd into the folder starter-code in this directory
  • npm install to bring down all the dependencies
  • node console.js to enter into a REPL where you can interact with your DB

####Tips

  • save your successful code into your text-editor for each successful step
  • <command> + <up> will bring you to the last thing you entered in the repl

Note: All your models will be nested inside an object db.

####Steps

1) Create a user

2) Create tweets embedded in that user

3) List all the users

4) List all tweets of a specific user

5) Create several ingredients

6) Create a food that references those ingredients

7) List all the Foods

8) List all the ingredients in a Food