SlideShare ist ein Scribd-Unternehmen logo
1 von 69
Build an application with MongoDB
Part 1: Creating a REST API using the ME(a)N stack
Chad Tindel
Senior Solution Architect
@ctindel
2
What is all this stuff?
3
• Introduction to the MEAN Stack
• What is a REST API?
• Creating our REST API
• Defining our Data Model
• Real-life authentication using Stormpath
• Javascript Quirks
• WRITE YOUR TESTS FIRST
• Let’s look at some application code
Agenda
4
This webinar will move fast
5
• M = MongoDB/Mongoose.js, the most popular
nosql operational database
• E = Express.js, a lightweight web application
framework
• A = Angular.js, a robust framework for creating
HTML5 and Javascript rich web applications
• N = Node.js, a server-side javascript interpreter
The MEAN Stack
A modern replacement for LAMP
What is a REST API?
7
• REST = “Representation State Transfer”
• Essentially it’s just a lighter weight, though not-
standardized, alternative to SOAP and WSDL XML-
based API protocols
• Uses a client-server model, where the server is actually
an HTTP server
• Client sends HTTP verbs (GET, POST, PUT, DELETE)
along with a URL and variable parameters that are
urlencoded
• The URL tells us what object to act on
• Server replies with a result code and valid JSON
What is a REST API?
8
• GET – When a client wants to read an object.
• POST – Went a client wants to insert/create an
object.
• PUT – When a client wants to update an object.
• DELETE – When a client wants to delete an
object
HTTP Verbs – Mapping to CRUD
9
• Some common codes we might use
– 200 – “OK”
– 201 – “Created” (Used with POST)
– 400 – “Bad Request” (Perhaps missing required
parameters)
– 401 – “Unauthorized” (Missing authentication
parameters)
– 403 – “Forbidden” (You were authenticated but lacking
required privileges)
– 404 – “Not Found”
• http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
HTTP Result Codes
10
• Things you might want to say to me me at this
point:
– “REST APIs aren’t sexy”
– “How am I supposed to show this off to my boss?”
– “My clients wants to see a fancy website or mobile app”
• REST APIs are a way for you to create a data
service enabling you to easily create all your
other applications
– HTML5 / Javascript
– Android
– iOS
Why are we starting with a REST API?
11
• Because all the VC Money is in creating apps that
are So-Lo-Mo-Co, lots of new startups don’t even
have a web interface, such as:
– Uber
– WhatsApp
– Postmates
– Wash.io
• Creating a REST API also allows other
companies/applications to easily plug-in to your
application as well, turning your application into a
platform and making it more powerful
New companies don’t have an HTML Interface
Creating our REST API
13
• We’ll be building an RSS Aggregation application, similar
to our dearly departed Google Reader
• Our application today will have two components
– The REST API
– The Feed Grabber
• Since the point of today’s talk is to learn about creating a
REST API and not the intricacies of RSS feeds, we won’t
be discussing the feed grabber
Let’s build an application!
14
• We’ll need to define data models for and store the
following data:
– Users
– RSS Feeds
– Feed Entries
– User Feed Subscriptions
– Which feed entries a user has already read
• We’ll need to allow users to:
– Create an account
– Subscribe/unsubscribe to feeds
– Read feed entries
– Mark feeds/entries as read or unread
Let’s build an application!
Data Models
15
{
"_id" : ObjectId("523b1153a2aa6a3233a913f8"),
"requiresAuthentication" : false,
"modifiedDate" : ISODate("2014-08-29T17:40:22Z"),
"permanentlyRemoved" : false,
"feedURL" : "http://feeds.feedburner.com/eater/nyc",
"title" : "Eater NY",
"bozoBitSet" : false,
"enabled" : true,
"etag" : "4bL78iLSZud2iXd/vd10mYC32BE",
"link" : "http://ny.eater.com/",
"permanentRedirectURL" : null,
"description" : "The New York City Restaurant, Bar, and Nightlife
Blog”
}
Data Model Design
Feed Collection
16
{
"_id" : ObjectId("523b1153a2aa6a3233a91412"),
"description" : "Buzzfeed asked a bunch of people…”,
"title" : "Cronut Mania: Buzzfeed asked a bunch of people...",
"summary" : "Buzzfeed asked a bunch of people that were…”,
"content" : [
{
"base" : "http://ny.eater.com/",
"type" : "text/html",
"value" : ”LOTS OF HTML HERE",
"language" : "en"
}
],
"entryID" : "tag:ny.eater.com,2013://4.560508",
"publishedDate" : ISODate("2013-09-17T20:45:20Z"),
"link" : "http://ny.eater.com/archives/2013/09/cronut_mania_41.php",
"feedID" : ObjectId("523b1153a2aa6a3233a913f8")
}
Data Model Design
Feed Entry Collection
17
{
"_id" : ObjectId("54ad6c3ae764de42070b27b1"),
"active" : true,
"email" : "testuser1@example.com",
"firstName" : "Test",
"lastName" : "User1",
"sp_api_key_id" : "6YQB0A8VXM0X8RVDPPLRHBI7J",
"sp_api_key_secret" : "veBw/YFx56Dl0bbiVEpvbjF”,
"lastLogin" : ISODate("2015-01-07T17:26:18.996Z"),
"created" : ISODate("2015-01-07T17:26:18.995Z"),
"subs" : [ ObjectId("523b1153a2aa6a3233a913f8"),
ObjectId("54b563c3a50a190b50f4d63b")],
}
Data Model Design
User Collection
18
{
"_id" : ObjectId("523b2fcc054b1b8c579bdb82"),
"read" : true,
"user_id" : ObjectId("54ad6c3ae764de42070b27b1"),
"feed_entry_id" : ObjectId("523b1153a2aa6a3233a91412"),
"feed_id" : ObjectId("523b1153a2aa6a3233a913f8")
}
Data Model Design
User-Feed-Entry Mapping Collection
19
• We’ll need to allow users to:
– Create an account
– Subscribe/unsubscribe to feeds
– Read feed entries
– Mark feeds/entries as read or unread
Let’s build an application!
User Actions
20
Creating our REST API
Route Verb Description Variables
/user/enroll POST Register a
new user
firstName
lastName
email
password
/user/resetPassword PUT Password
Reset
email
/feeds GET Get feed
subscriptions
for each user
with
description
and unread
count
/feeds/subscribe PUT Subscribe to
a new feed
feedURL
21
Creating our REST API
Route Verb Description Variables
/feeds/entries GET Get all entries
for feeds the
user is
subscribed to
/feeds/<feedid>/entries GET Get all entries
for a specific
feed
/feeds/<feedid> PUT Mark all
entries for a
specific feed
as read or
unread
read = <true
| false>
22
Creating our REST API
Route Verb Description Variables
/feeds/<feedid>/entries/<entryid> PUT Mark a
specific entry
as either read
or unread
read = <true
| false>
/feeds/<feedid> DELETE Unsubscribe
from this
particular
feed
Real Life Authentication with
Stormpath
24
Using Stormpath for Authentication
• “User Management as a
Service”
– Authentication
– Authorization
– API Keys
• REST JSON API +
– Node SDK
– Express Plugin
– Passport Plugin
25
Using Stormpath for Authentication
• Stormpath will give us a secret key for each “Application” we
define with them. These applications can be “Reader Prod”,
“Reader Test”, etc.
• Stormpath will give us an API Key Properties file as well
• We can define password strength requirements for each
application, like
– Must have >= 8 characters
– Must include lowercase and uppercase
– Must include a number
– Must include a non-alphabetic character
• Stormpath keeps track of all of our users and assigns them
API Keys which we can use for our REST API Authentication
Javascript / Node.js Overview
27
Creating a Node.js Application
• Install node.js
– http://nodejs.org/download/
• Node.js applications are built using a lot of library modules
• You define a package.json file describing your application and
all of it’s library dependencies
• You use the Node.js Package Manager to install a copy of
those libraries in a subdirectory of your application
(node_modules/) instead of a system directly (like /usr/lib) to
avoid the problem of different apps needing different and
conflicting library versions
• Run “npm install” and it will create the node_modules/ with all
of your required libraries
28
Our package.json
{
"name": "reader-api",
"main": "server.js",
"dependencies": {
"express" : "~4.10.0",
"stormpath" : "~0.7.5", "express-stormpath" : "~0.5.9",
"mongodb" : "~1.4.26”, "mongoose" : "~3.8.0",
"body-parser" : "~1.10.0”, "method-override" : "~2.3.0",
"morgan" : "~1.5.0”, "winston" : "~0.8.3”, "express-winston" : "~0.2.9",
"validator" : "~3.27.0",
"path" : "~0.4.9",
"errorhandler" : "~1.3.0",
"frisby" : "~0.8.3",
"jasmine-node" : "~1.14.5",
"async" : "~0.9.0"
}
}
29
Async Code in Javascript
function foo() {
someAsyncFunction(params, function(err, results) {
console.log(“one”);
});
console.log(“two”);
}
At first glance you might expect the output to be:
one
two
But actually it’s the reverse because the line that prints “one”
happens later, asynchronously, in the callback
30
Async Library
https://github.com/caolan/async
actionArray = [
function one(cb) {
someAsyncFunction(params, function(err, results) {
if (err) {
cb(new Error(“There was an error”));
}
console.log(“one”);
cb(null);
});
},
function two(cb) {
console.log(“two”);
cb(null);
}]
]
Async.series(actionArray);
Write your tests first
32
Defining some utility libraries
test/config/test_config.js
module.exports = {
url : 'http://localhost:8000/api/v1.0'
}
33
Defining some utility libraries
test/setup_tests.js
function connectDB(callback) {
mongoClient.connect(dbConfig.testDBURL, function(err, db) {
assert.equal(null, err);
reader_test_db = db;
console.log("Connected correctly to server");
callback(0);
});
}
34
Defining some utility libraries
test/setup_tests.js (continued)
function dropUserCollection(callback) {
console.log("dropUserCollection");
user = reader_test_db.collection('user');
if (undefined != user) {
user.drop(function(err, reply) {
console.log('user collection dropped');
callback(0);
});
} else {
callback(0);
}
},
35
Defining some utility libraries
test/setup_tests.js (continued)
function dropUserFeedEntryCollection(callback) {
console.log("dropUserFeedEntryCollection");
user_feed_entry = reader_test_db.collection('user_feed_entry');
if (undefined != user_feed_entry) {
user_feed_entry.drop(function(err, reply) {
console.log('user_feed_entry collection dropped');
callback(0);
});
} else {
callback(0);
}
}
36
Defining some utility libraries
test/setup_tests.js (continued)
function getApplication(callback) {
console.log("getApplication");
client.getApplications({name: SP_APP_NAME}, function(err, applications) {
console.log(applications);
if (err) {
log("Error in getApplications");
throw err;
}
app = applications.items[0];
callback(0);
});
},
37
Defining some utility libraries
test/setup_tests.js (continued)
function deleteTestAccounts(callback) {
app.getAccounts({email: TU_EMAIL_REGEX}, function(err, accounts) {
if (err) throw err;
accounts.items.forEach(function deleteAccount(account) {
account.delete(function deleteError(err) {
if (err) throw err;
});
});
callback(0);
});
}
function closeDB(callback) {
reader_test_db.close();
}
async.series([connectDB, dropUserCollection, dropUserFeedEntryCollection,
dropUserFeedEntryCollection, getApplication, deleteTestAccounts,
closeDB);
38
Using frisby.js to define test cases
test/create_accounts_error_spec.js
TU1_FN = "Test";
TU1_LN = "User1";
TU1_EMAIL = "testuser1@example.com";
TU1_PW = "testUser123";
TU_EMAIL_REGEX = 'testuser*';
SP_APP_NAME = 'Reader Test';
var frisby = require('frisby');
var tc = require('./config/test_config');
frisby.create('POST missing firstName')
.post(tc.url + '/user/enroll',
{ 'lastName' : TU1_LN,
'email' : TU1_EMAIL,
'password' : TU1_PW })
.expectStatus(400)
.expectHeader('Content-Type', 'application/json; charset=utf-8')
.expectJSON({'error' : 'Undefined First Name'})
.toss()
39
Using frisby.js to define test cases
test/create_accounts_error_spec.js (continued)
frisby.create('POST password missing lowercase')
.post(tc.url + '/user/enroll',
{ 'firstName' : TU1_FN,
'lastName' : TU1_LN,
'email' : TU1_EMAIL,
'password' : 'TESTUSER123' })
.expectStatus(400)
.expectHeader('Content-Type', 'application/json; charset=utf-8')
.expectJSONTypes({'error' : String})
.toss()
40
Using frisby.js to define test cases
test/create_accounts_error_spec.js (continued)
frisby.create('POST invalid email address')
.post(tc.url + '/user/enroll',
{ 'firstName' : TU1_FN,
'lastName' : TU1_LN,
'email' : "invalid.email",
'password' : 'testUser' })
.expectStatus(400)
.expectHeader('Content-Type', 'application/json; charset=utf-8')
.expectJSONTypes({'error' : String})
.toss()
41
Using frisby.js to define test cases
test/create_accounts_spec.js
TEST_USERS = [{'fn' : 'Test', 'ln' : 'User1',
'email' : 'testuser1@example.com', 'pwd' : 'testUser123'},
{'fn' : 'Test', 'ln' : 'User2',
'email' : 'testuser2@example.com', 'pwd' : 'testUser123'},
{'fn' : 'Test', 'ln' : 'User3',
'email' : 'testuser3@example.com', 'pwd' : 'testUser123'}]
SP_APP_NAME = 'Reader Test';
var frisby = require('frisby');
var tc = require('./config/test_config');
42
Using frisby.js to define test cases
test/create_accounts_spec.js (continued)
TEST_USERS.forEach(function createUser(user, index, array) {
frisby.create('POST enroll user ' + user.email)
.post(tc.url + '/user/enroll',
{ 'firstName' : user.fn,
'lastName' : user.ln,
'email' : user.email,
'password' : user.pwd })
.expectStatus(201)
.expectHeader('Content-Type', 'application/json; charset=utf-8')
.expectJSON({ 'firstName' : user.fn,
'lastName' : user.ln,
'email' : user.email })
.toss()
});
43
Using frisby.js to define test cases
test/create_accounts_spec.js (continued)
frisby.create('POST enroll duplicate user ')
.post(tc.url + '/user/enroll',
{ 'firstName' : TEST_USERS[0].fn,
'lastName' : TEST_USERS[0].ln,
'email' : TEST_USERS[0].email,
'password' : TEST_USERS[0].pwd })
.expectStatus(400)
.expectHeader('Content-Type', 'application/json; charset=utf-8')
.expectJSON({'error' : 'Account with that email already exists. Please choose
another email.'})
.toss()
44
Using frisby.js to define test cases
Need to create /tmp/readerTestCreds.js
We want to dynamically create a file that looks like this for us to use in defining
test cases that require us to authenticate a user:
TEST_USERS =
[{ "_id":"54ad6c3ae764de42070b27b1",
"email":"testuser1@example.com",
"firstName":"Test",
"lastName":"User1",
"sp_api_key_id":”<API KEY ID>",
"sp_api_key_secret":”<API KEY SECRET>”
},
{ "_id":"54ad6c3be764de42070b27b2”,
"email":"testuser2@example.com",
"firstName":"Test",
"lastName":"User2”,
"sp_api_key_id":”<API KEY ID>",
"sp_api_key_secret":”<API KEY SECRET>”
}];
module.exports = TEST_USERS;
45
Using frisby.js to define test cases
tests/writeCreds.js
TU_EMAIL_REGEX = new RegExp('^testuser*');
SP_APP_NAME = 'Reader Test';
TEST_CREDS_TMP_FILE = '/tmp/readerTestCreds.js';
var async = require('async');
var dbConfig = require('./config/db.js');
var mongodb = require('mongodb');
assert = require('assert');
var mongoClient = mongodb.MongoClient
var reader_test_db = null;
var users_array = null;
46
Using frisby.js to define test cases
tests/writeCreds.js (continued)
function connectDB(callback) {
mongoClient.connect(dbConfig.testDBURL, function(err, db) {
assert.equal(null, err);
reader_test_db = db;
callback(null);
});
}
function lookupUserKeys(callback) {
console.log("lookupUserKeys");
user_coll = reader_test_db.collection('user');
user_coll.find({email : TU_EMAIL_REGEX}).toArray(function(err, users) {
users_array = users;
callback(null);
});
}
47
Using frisby.js to define test cases
tests/writeCreds.js (continued)
function writeCreds(callback) {
var fs = require('fs');
fs.writeFileSync(TEST_CREDS_TMP_FILE, 'TEST_USERS = ');
fs.appendFileSync(TEST_CREDS_TMP_FILE, JSON.stringify(users_array));
fs.appendFileSync(TEST_CREDS_TMP_FILE, '; module.exports = TEST_USERS;');
callback(0);
}
function closeDB(callback) {
reader_test_db.close();
}
async.series([connectDB, lookupUserKeys, writeCreds, closeDB]);
48
Using frisby.js to define test cases
tests/feed_spec.js
TEST_USERS = require('/tmp/readerTestCreds.js');
var frisby = require('frisby');
var tc = require('./config/test_config');
var async = require('async');
var dbConfig = require('./config/db.js');
var dilbertFeedURL = 'http://feeds.feedburner.com/DilbertDailyStrip';
var nycEaterFeedURL = 'http://feeds.feedburner.com/eater/nyc';
function addEmptyFeedListTest(callback) {
var user = TEST_USERS[0];
frisby.create('GET empty feed list for user ' + user.email)
.get(tc.url + '/feeds')
.auth(user.sp_api_key_id, user.sp_api_key_secret)
.expectStatus(200)
.expectHeader('Content-Type', 'application/json; charset=utf-8')
.expectJSON({feeds : []})
.toss()
callback(null);
}
49
Using frisby.js to define test cases
tests/feed_spec.js
function subOneFeed(callback) {
var user = TEST_USERS[0];
frisby.create('PUT Add feed sub for user ' + user.email)
.put(tc.url + '/feeds/subscribe',
{'feedURL' : dilbertFeedURL})
.auth(user.sp_api_key_id, user.sp_api_key_secret)
.expectStatus(201)
.expectHeader('Content-Type', 'application/json; charset=utf-8')
.expectJSONLength('user.subs', 1)
.toss()
callback(null);
}
50
Using frisby.js to define test cases
tests/feed_spec.js
function subDuplicateFeed(callback) {
var user = TEST_USERS[0];
frisby.create('PUT Add duplicate feed sub for user ' + user.email)
.put(tc.url + '/feeds/subscribe',
{'feedURL' : dilbertFeedURL})
.auth(user.sp_api_key_id, user.sp_api_key_secret)
.expectStatus(201)
.expectHeader('Content-Type', 'application/json; charset=utf-8')
.expectJSONLength('user.subs', 1)
.toss()
callback(null);
}
51
Using frisby.js to define test cases
tests/feed_spec.js
function subSecondFeed(callback) {
var user = TEST_USERS[0];
frisby.create('PUT Add second feed sub for user ' + user.email)
.put(tc.url + '/feeds/subscribe',
{'feedURL' : nycEaterFeedURL})
.auth(user.sp_api_key_id, user.sp_api_key_secret)
.expectStatus(201)
.expectHeader('Content-Type', 'application/json; charset=utf-8')
.expectJSONLength('user.subs', 2)
.toss()
callback(null);
}
52
Using frisby.js to define test cases
tests/feed_spec.js
function subOneFeedSecondUser(callback) {
var user = TEST_USERS[1];
frisby.create('PUT Add one feed sub for second user ' + user.email)
.put(tc.url + '/feeds/subscribe',
{'feedURL' : nycEaterFeedURL})
.auth(user.sp_api_key_id, user.sp_api_key_secret)
.expectStatus(201)
.expectHeader('Content-Type', 'application/json; charset=utf-8')
.expectJSONLength('user.subs', 1)
.toss()
callback(null);
}
async.series([addEmptyFeedListTest, subOneFeed, subDuplicateFeed,
subSecondFeed, subOneFeedSecondUser]);
Can we FINALLY build our REST
API code?
54
Defining some utility libraries
config/db.js
module.exports = {
url : 'mongodb://localhost/reader_test'
}
// If we wanted to have different database URLs for Dev/QA/Prod we could have
// those here
55
Defining some utility libraries
config/security.js
module.exports = {
stormpath_secret_key : ‘YOUR STORMPATH APPLICATION KEY’;
}
// If we wanted to turn on database authentication we could put that here
// This file will NOT get checked into source code control for obvious reasons
56
Defining some utility libraries
config/stormpath_apikey.properties
apiKey.id = YOUR STORMPATH API KEY ID
apiKey.secret = YOUR STORMPATH API KEY SECRET
57
Express.js Overview
• In express.js you create an “application” (app)
• That application listens on a particular port for HTTP requests
to come in
• When requests come in, they pass through a middleware
chain
– Each link in the middleware chain is given a req (the
request) object and a res object (to store the results)
– Each link can choose to do work, or pass it to the next link
• We add new middleware via app.use()
• The main middleware is called our “router”, which looks at the
URL and routes each different URL/Verb combo to a specific
handler function
58
Creating our application!
server.js
var express = require('express');
var bodyParser = require('body-parser');
var mongoose = require('mongoose');
var stormpath = require('express-stormpath');
var routes = require("./app/routes");
var db = require('./config/db');
var security = require('./config/security');
var app = express();
var morgan = require('morgan’);
app.use(morgan);
app.use(stormpath.init(app, {
apiKeyFile: './config/stormpath_apikey.properties',
application: ‘YOUR SP APPLICATION URL',
secretKey: security.stormpath_secret_key
}));
var port = 8000;
mongoose.connect(db.url);
59
Creating our application!
server.js (continued)
app.use(bodyParser.urlencoded({ extended: true }));
routes.addAPIRouter(app, mongoose, stormpath);
// Define our own middleware at the end of the chain to handle bad URLs
app.use(function(req, res, next){
res.status(404);
res.json({ error: 'Invalid URL' });
});
app.listen(port);
// shoutout to the user
console.log('Magic happens on port ' + port);
// expose app
exports = module.exports = app;
60
Defining our Mongoose Data Models
app/routes.js
var userSchema = new mongoose.Schema({
active: Boolean,
email: { type: String, trim: true, lowercase: true },
firstName: { type: String, trim: true },
lastName: { type: String, trim: true },
sp_api_key_id: { type: String, trim: true },
sp_api_key_secret: { type: String, trim: true },
subs: { type: [mongoose.Schema.Types.ObjectId], default: [] },
created: { type: Date, default: Date.now },
lastLogin: { type: Date, default: Date.now },
},
{ collection: 'user' }
);
userSchema.index({email : 1}, {unique:true});
userSchema.index({sp_api_key_id : 1}, {unique:true});
var UserModel = mongoose.model( 'User', userSchema );
61
Defining our Mongoose Data Models
app/routes.js (continued)
var feedSchema = new mongoose.Schema({
feedURL: { type: String, trim:true },
link: { type: String, trim:true },
description: { type: String, trim:true },
state: { type: String, trim:true, lowercase:true, default: 'new' },
createdDate: { type: Date, default: Date.now },
modifiedDate: { type: Date, default: Date.now },
},
{ collection: 'feed' }
);
feedSchema.index({feedURL : 1}, {unique:true});
feedSchema.index({link : 1}, {unique:true, sparse:true});
var FeedModel = mongoose.model( 'Feed', feedSchema );
62
Defining our Mongoose Data Models
app/routes.js (continued)
var feedEntrySchema = new mongoose.Schema({
description: { type: String, trim:true },
title: { type: String, trim:true },
summary: { type: String, trim:true },
entryID: { type: String, trim:true },
publishedDate: { type: Date },
link: { type: String, trim:true },
feedID: { type: mongoose.Schema.Types.ObjectId },
state: { type: String, trim:true, lowercase:true, default: 'new' },
created: { type: Date, default: Date.now },
},
{ collection: 'feedEntry' }
);
feedEntrySchema.index({entryID : 1});
feedEntrySchema.index({feedID : 1});
var FeedEntryModel = mongoose.model( 'FeedEntry', feedEntrySchema );
63
Defining our Mongoose Data Models
app/routes.js (continued)
var userFeedEntrySchema = new mongoose.Schema({
userID: { type: mongoose.Schema.Types.ObjectId },
feedEntryID: { type: mongoose.Schema.Types.ObjectId },
feedID: { type: mongoose.Schema.Types.ObjectId },
read : { type: Boolean, default: false },
},
{ collection: 'userFeedEntry' }
);
userFeedEntrySchema.index({userID : 1, feedID : 1, feedEntryID : 1, read : 1});
var UserFeedEntryModel = mongoose.model('UserFeedEntry',
userFeedEntrySchema );
64
Defining our Routes
app/routes.js (continued)
exports.addAPIRouter = function(app, mongoose, stormpath) {
app.get('/*', function(req, res, next) {
res.contentType('application/json');
next();
});
app.post('/*', function(req, res, next) {
res.contentType('application/json');
next();
});
app.put('/*', function(req, res, next) {
res.contentType('application/json');
next();
});
app.delete('/*', function(req, res, next) {
res.contentType('application/json');
next();
});
65
Defining our Routes
app/routes.js (continued)
var router = express.Router();
router.post('/user/enroll', function(req, res) {
logger.debug('Router for /user/enroll');
…
}
router.get('/feeds', stormpath.apiAuthenticationRequired, function(req, res) {
logger.debug('Router for /feeds');
…
}
router.put('/feeds/subscribe',
stormpath.apiAuthenticationRequired, function(req, res) {
logger.debug('Router for /feeds');
…
}
app.use('/api/v1.0', router);
}
66
Looking at our router code
Let’s go look at some real router code at:
https://github.com/ctindel/reader/blob/master/api/v1.0/app/routes.js
67
Starting the server and running tests
• Make sure your mongodb instance is running
– mongod
• Install the Node Libraries
– npm install
• Start the REST API server
– node server.js
• Run test cases
– node setup_tests.js
– jasmine-node create_accounts_error_spec.js
– jasmine-node create_accounts_spec.js
– node write_creds.js
– jasmine-node feed_spec.js
68
For More Information
Resource Location
My github repo github.com/ctindel/reader
MongoDB Downloads mongodb.com/download
Free Online Training education.mongodb.com
Webinars and Events mongodb.com/events
White Papers mongodb.com/white-papers
Case Studies mongodb.com/customers
Presentations mongodb.com/presentations
Documentation docs.mongodb.org
Additional Info info@mongodb.com
Resource Location
Building Your First App with MongoDB

Weitere ähnliche Inhalte

Was ist angesagt?

Consuming RESTful services in PHP
Consuming RESTful services in PHPConsuming RESTful services in PHP
Consuming RESTful services in PHPZoran Jeremic
 
Creating And Consuming Web Services In Php 5
Creating And Consuming Web Services In Php 5Creating And Consuming Web Services In Php 5
Creating And Consuming Web Services In Php 5Michael Girouard
 
Updates to the java api for json processing for java ee 8
Updates to the java api for json processing for java ee 8Updates to the java api for json processing for java ee 8
Updates to the java api for json processing for java ee 8Alex Soto
 
Spring Web Services: SOAP vs. REST
Spring Web Services: SOAP vs. RESTSpring Web Services: SOAP vs. REST
Spring Web Services: SOAP vs. RESTSam Brannen
 
Restful Web Services
Restful Web ServicesRestful Web Services
Restful Web ServicesAngelin R
 
Building a Backend with Flask
Building a Backend with FlaskBuilding a Backend with Flask
Building a Backend with FlaskMake School
 
REST Easy with AngularJS - ng-grid CRUD EXAMPLE
REST Easy with AngularJS - ng-grid CRUD EXAMPLEREST Easy with AngularJS - ng-grid CRUD EXAMPLE
REST Easy with AngularJS - ng-grid CRUD EXAMPLEreneechemel
 
Understanding REST
Understanding RESTUnderstanding REST
Understanding RESTNitin Pande
 
Java Configuration Deep Dive with Spring
Java Configuration Deep Dive with SpringJava Configuration Deep Dive with Spring
Java Configuration Deep Dive with SpringJoshua Long
 
Introducing RaveJS: Spring Boot concepts for JavaScript applications
Introducing RaveJS: Spring Boot concepts for JavaScript applicationsIntroducing RaveJS: Spring Boot concepts for JavaScript applications
Introducing RaveJS: Spring Boot concepts for JavaScript applicationsJohn Hann
 
Multi Client Development with Spring for SpringOne 2GX 2013 with Roy Clarkson
Multi Client Development with Spring for SpringOne 2GX 2013 with Roy ClarksonMulti Client Development with Spring for SpringOne 2GX 2013 with Roy Clarkson
Multi Client Development with Spring for SpringOne 2GX 2013 with Roy ClarksonJoshua Long
 
Lessons Learned from Building a Multi-Tenant Saas Content Management System o...
Lessons Learned from Building a Multi-Tenant Saas Content Management System o...Lessons Learned from Building a Multi-Tenant Saas Content Management System o...
Lessons Learned from Building a Multi-Tenant Saas Content Management System o...MongoDB
 
External Data Access with jQuery
External Data Access with jQueryExternal Data Access with jQuery
External Data Access with jQueryDoncho Minkov
 
Building Beautiful REST APIs in ASP.NET Core
Building Beautiful REST APIs in ASP.NET CoreBuilding Beautiful REST APIs in ASP.NET Core
Building Beautiful REST APIs in ASP.NET CoreStormpath
 
Using the SugarCRM REST API
Using the SugarCRM REST APIUsing the SugarCRM REST API
Using the SugarCRM REST APIAsa Kusuma
 

Was ist angesagt? (20)

Consuming RESTful services in PHP
Consuming RESTful services in PHPConsuming RESTful services in PHP
Consuming RESTful services in PHP
 
Creating And Consuming Web Services In Php 5
Creating And Consuming Web Services In Php 5Creating And Consuming Web Services In Php 5
Creating And Consuming Web Services In Php 5
 
Develop webservice in PHP
Develop webservice in PHPDevelop webservice in PHP
Develop webservice in PHP
 
Updates to the java api for json processing for java ee 8
Updates to the java api for json processing for java ee 8Updates to the java api for json processing for java ee 8
Updates to the java api for json processing for java ee 8
 
Spring Web Services: SOAP vs. REST
Spring Web Services: SOAP vs. RESTSpring Web Services: SOAP vs. REST
Spring Web Services: SOAP vs. REST
 
Restful Web Services
Restful Web ServicesRestful Web Services
Restful Web Services
 
Building a Backend with Flask
Building a Backend with FlaskBuilding a Backend with Flask
Building a Backend with Flask
 
REST Easy with AngularJS - ng-grid CRUD EXAMPLE
REST Easy with AngularJS - ng-grid CRUD EXAMPLEREST Easy with AngularJS - ng-grid CRUD EXAMPLE
REST Easy with AngularJS - ng-grid CRUD EXAMPLE
 
Understanding REST
Understanding RESTUnderstanding REST
Understanding REST
 
Java Configuration Deep Dive with Spring
Java Configuration Deep Dive with SpringJava Configuration Deep Dive with Spring
Java Configuration Deep Dive with Spring
 
Introducing RaveJS: Spring Boot concepts for JavaScript applications
Introducing RaveJS: Spring Boot concepts for JavaScript applicationsIntroducing RaveJS: Spring Boot concepts for JavaScript applications
Introducing RaveJS: Spring Boot concepts for JavaScript applications
 
AJAX - An introduction
AJAX - An introductionAJAX - An introduction
AJAX - An introduction
 
HTML5 - An introduction
HTML5 - An introductionHTML5 - An introduction
HTML5 - An introduction
 
Day01 api
Day01   apiDay01   api
Day01 api
 
Multi Client Development with Spring for SpringOne 2GX 2013 with Roy Clarkson
Multi Client Development with Spring for SpringOne 2GX 2013 with Roy ClarksonMulti Client Development with Spring for SpringOne 2GX 2013 with Roy Clarkson
Multi Client Development with Spring for SpringOne 2GX 2013 with Roy Clarkson
 
Lessons Learned from Building a Multi-Tenant Saas Content Management System o...
Lessons Learned from Building a Multi-Tenant Saas Content Management System o...Lessons Learned from Building a Multi-Tenant Saas Content Management System o...
Lessons Learned from Building a Multi-Tenant Saas Content Management System o...
 
Angularjs & REST
Angularjs & RESTAngularjs & REST
Angularjs & REST
 
External Data Access with jQuery
External Data Access with jQueryExternal Data Access with jQuery
External Data Access with jQuery
 
Building Beautiful REST APIs in ASP.NET Core
Building Beautiful REST APIs in ASP.NET CoreBuilding Beautiful REST APIs in ASP.NET Core
Building Beautiful REST APIs in ASP.NET Core
 
Using the SugarCRM REST API
Using the SugarCRM REST APIUsing the SugarCRM REST API
Using the SugarCRM REST API
 

Andere mochten auch

Leveraging MongoDB as a Data Store for Security Data
Leveraging MongoDB as a Data Store for Security DataLeveraging MongoDB as a Data Store for Security Data
Leveraging MongoDB as a Data Store for Security DataMongoDB
 
MongoDB Days UK: Building an Enterprise Data Fabric at Royal Bank of Scotland...
MongoDB Days UK: Building an Enterprise Data Fabric at Royal Bank of Scotland...MongoDB Days UK: Building an Enterprise Data Fabric at Royal Bank of Scotland...
MongoDB Days UK: Building an Enterprise Data Fabric at Royal Bank of Scotland...MongoDB
 
Querying data on the Web – client or server?
Querying data on the Web – client or server?Querying data on the Web – client or server?
Querying data on the Web – client or server?Ruben Verborgh
 
Couchbase Server 2.0 - Indexing and Querying - Deep dive
Couchbase Server 2.0 - Indexing and Querying - Deep diveCouchbase Server 2.0 - Indexing and Querying - Deep dive
Couchbase Server 2.0 - Indexing and Querying - Deep diveDipti Borkar
 
Paris data-geeks-2013-03-28
Paris data-geeks-2013-03-28Paris data-geeks-2013-03-28
Paris data-geeks-2013-03-28Ted Dunning
 
Big Data Analysis Patterns - TriHUG 6/27/2013
Big Data Analysis Patterns - TriHUG 6/27/2013Big Data Analysis Patterns - TriHUG 6/27/2013
Big Data Analysis Patterns - TriHUG 6/27/2013boorad
 
Development Platform as a Service - erfarenheter efter ett års användning - ...
Development Platform as a Service - erfarenheter efter ett års användning -  ...Development Platform as a Service - erfarenheter efter ett års användning -  ...
Development Platform as a Service - erfarenheter efter ett års användning - ...IBM Sverige
 
MongoDB Days UK: Using MongoDB and Python for Data Analysis Pipelines
MongoDB Days UK: Using MongoDB and Python for Data Analysis PipelinesMongoDB Days UK: Using MongoDB and Python for Data Analysis Pipelines
MongoDB Days UK: Using MongoDB and Python for Data Analysis PipelinesMongoDB
 
Apache Airflow (incubating) NL HUG Meetup 2016-07-19
Apache Airflow (incubating) NL HUG Meetup 2016-07-19Apache Airflow (incubating) NL HUG Meetup 2016-07-19
Apache Airflow (incubating) NL HUG Meetup 2016-07-19Bolke de Bruin
 
Using MongoDB + Hadoop Together
Using MongoDB + Hadoop TogetherUsing MongoDB + Hadoop Together
Using MongoDB + Hadoop TogetherMongoDB
 
OpenStack Heat slides
OpenStack Heat slidesOpenStack Heat slides
OpenStack Heat slidesdbelova
 
Cassandra at Instagram (August 2013)
Cassandra at Instagram (August 2013)Cassandra at Instagram (August 2013)
Cassandra at Instagram (August 2013)Rick Branson
 
A user's perspective on SaltStack and other configuration management tools
A user's perspective on SaltStack and other configuration management toolsA user's perspective on SaltStack and other configuration management tools
A user's perspective on SaltStack and other configuration management toolsSaltStack
 
Introduction to Apache Airflow - Data Day Seattle 2016
Introduction to Apache Airflow - Data Day Seattle 2016Introduction to Apache Airflow - Data Day Seattle 2016
Introduction to Apache Airflow - Data Day Seattle 2016Sid Anand
 
MongoDB for Time Series Data Part 2: Analyzing Time Series Data Using the Agg...
MongoDB for Time Series Data Part 2: Analyzing Time Series Data Using the Agg...MongoDB for Time Series Data Part 2: Analyzing Time Series Data Using the Agg...
MongoDB for Time Series Data Part 2: Analyzing Time Series Data Using the Agg...MongoDB
 
Webinar: 10-Step Guide to Creating a Single View of your Business
Webinar: 10-Step Guide to Creating a Single View of your BusinessWebinar: 10-Step Guide to Creating a Single View of your Business
Webinar: 10-Step Guide to Creating a Single View of your BusinessMongoDB
 
MongoDB Schema Design: Four Real-World Examples
MongoDB Schema Design: Four Real-World ExamplesMongoDB Schema Design: Four Real-World Examples
MongoDB Schema Design: Four Real-World ExamplesMike Friedman
 

Andere mochten auch (19)

Leveraging MongoDB as a Data Store for Security Data
Leveraging MongoDB as a Data Store for Security DataLeveraging MongoDB as a Data Store for Security Data
Leveraging MongoDB as a Data Store for Security Data
 
MongoDB Days UK: Building an Enterprise Data Fabric at Royal Bank of Scotland...
MongoDB Days UK: Building an Enterprise Data Fabric at Royal Bank of Scotland...MongoDB Days UK: Building an Enterprise Data Fabric at Royal Bank of Scotland...
MongoDB Days UK: Building an Enterprise Data Fabric at Royal Bank of Scotland...
 
Querying data on the Web – client or server?
Querying data on the Web – client or server?Querying data on the Web – client or server?
Querying data on the Web – client or server?
 
Couchbase Server 2.0 - Indexing and Querying - Deep dive
Couchbase Server 2.0 - Indexing and Querying - Deep diveCouchbase Server 2.0 - Indexing and Querying - Deep dive
Couchbase Server 2.0 - Indexing and Querying - Deep dive
 
Paris data-geeks-2013-03-28
Paris data-geeks-2013-03-28Paris data-geeks-2013-03-28
Paris data-geeks-2013-03-28
 
Big Data Analysis Patterns - TriHUG 6/27/2013
Big Data Analysis Patterns - TriHUG 6/27/2013Big Data Analysis Patterns - TriHUG 6/27/2013
Big Data Analysis Patterns - TriHUG 6/27/2013
 
Development Platform as a Service - erfarenheter efter ett års användning - ...
Development Platform as a Service - erfarenheter efter ett års användning -  ...Development Platform as a Service - erfarenheter efter ett års användning -  ...
Development Platform as a Service - erfarenheter efter ett års användning - ...
 
MongoDB Days UK: Using MongoDB and Python for Data Analysis Pipelines
MongoDB Days UK: Using MongoDB and Python for Data Analysis PipelinesMongoDB Days UK: Using MongoDB and Python for Data Analysis Pipelines
MongoDB Days UK: Using MongoDB and Python for Data Analysis Pipelines
 
Apache Airflow (incubating) NL HUG Meetup 2016-07-19
Apache Airflow (incubating) NL HUG Meetup 2016-07-19Apache Airflow (incubating) NL HUG Meetup 2016-07-19
Apache Airflow (incubating) NL HUG Meetup 2016-07-19
 
Using MongoDB + Hadoop Together
Using MongoDB + Hadoop TogetherUsing MongoDB + Hadoop Together
Using MongoDB + Hadoop Together
 
OpenStack Heat slides
OpenStack Heat slidesOpenStack Heat slides
OpenStack Heat slides
 
Cassandra at Instagram (August 2013)
Cassandra at Instagram (August 2013)Cassandra at Instagram (August 2013)
Cassandra at Instagram (August 2013)
 
A user's perspective on SaltStack and other configuration management tools
A user's perspective on SaltStack and other configuration management toolsA user's perspective on SaltStack and other configuration management tools
A user's perspective on SaltStack and other configuration management tools
 
storm at twitter
storm at twitterstorm at twitter
storm at twitter
 
Introduction to Apache Airflow - Data Day Seattle 2016
Introduction to Apache Airflow - Data Day Seattle 2016Introduction to Apache Airflow - Data Day Seattle 2016
Introduction to Apache Airflow - Data Day Seattle 2016
 
MongoDB for Time Series Data Part 2: Analyzing Time Series Data Using the Agg...
MongoDB for Time Series Data Part 2: Analyzing Time Series Data Using the Agg...MongoDB for Time Series Data Part 2: Analyzing Time Series Data Using the Agg...
MongoDB for Time Series Data Part 2: Analyzing Time Series Data Using the Agg...
 
Hadoop on the Cloud
Hadoop on the CloudHadoop on the Cloud
Hadoop on the Cloud
 
Webinar: 10-Step Guide to Creating a Single View of your Business
Webinar: 10-Step Guide to Creating a Single View of your BusinessWebinar: 10-Step Guide to Creating a Single View of your Business
Webinar: 10-Step Guide to Creating a Single View of your Business
 
MongoDB Schema Design: Four Real-World Examples
MongoDB Schema Design: Four Real-World ExamplesMongoDB Schema Design: Four Real-World Examples
MongoDB Schema Design: Four Real-World Examples
 

Ähnlich wie Building Your First App with MongoDB

IBM Integration Bus and REST APIs - Sanjay Nagchowdhury
IBM Integration Bus and REST APIs - Sanjay NagchowdhuryIBM Integration Bus and REST APIs - Sanjay Nagchowdhury
IBM Integration Bus and REST APIs - Sanjay NagchowdhuryKaren Broughton-Mabbitt
 
MongoDB Days UK: Building Apps with the MEAN Stack
MongoDB Days UK: Building Apps with the MEAN StackMongoDB Days UK: Building Apps with the MEAN Stack
MongoDB Days UK: Building Apps with the MEAN StackMongoDB
 
RESTful API-centric Universe
RESTful API-centric UniverseRESTful API-centric Universe
RESTful API-centric UniverseTihomir Opačić
 
ASP.NET Mvc 4 web api
ASP.NET Mvc 4 web apiASP.NET Mvc 4 web api
ASP.NET Mvc 4 web apiTiago Knoch
 
Hia 1691-using iib-to_support_api_economy
Hia 1691-using iib-to_support_api_economyHia 1691-using iib-to_support_api_economy
Hia 1691-using iib-to_support_api_economyAndrew Coleman
 
Resting on your laurels will get you powned
Resting on your laurels will get you pownedResting on your laurels will get you powned
Resting on your laurels will get you pownedDinis Cruz
 
REST API 20.2 - Appworks Gateway Integration.pptx
REST API 20.2 - Appworks Gateway Integration.pptxREST API 20.2 - Appworks Gateway Integration.pptx
REST API 20.2 - Appworks Gateway Integration.pptxJason452803
 
Integrate MongoDB & SQL data with a single REST API
Integrate MongoDB & SQL data with a single REST APIIntegrate MongoDB & SQL data with a single REST API
Integrate MongoDB & SQL data with a single REST APIEspresso Logic
 
Reactive application using meteor
Reactive application using meteorReactive application using meteor
Reactive application using meteorSapna Upreti
 
SFScon 2020 - Nikola Milisavljevic - BASE - Python REST API framework
SFScon 2020 - Nikola Milisavljevic - BASE - Python REST API frameworkSFScon 2020 - Nikola Milisavljevic - BASE - Python REST API framework
SFScon 2020 - Nikola Milisavljevic - BASE - Python REST API frameworkSouth Tyrol Free Software Conference
 
MSWD:MERN STACK WEB DEVELOPMENT COURSE CODE
MSWD:MERN STACK WEB DEVELOPMENT COURSE CODEMSWD:MERN STACK WEB DEVELOPMENT COURSE CODE
MSWD:MERN STACK WEB DEVELOPMENT COURSE CODEannalakshmi35
 
(ATS6-PLAT04) Query service
(ATS6-PLAT04) Query service (ATS6-PLAT04) Query service
(ATS6-PLAT04) Query service BIOVIA
 
How to – wrap soap web service around a database
How to – wrap soap web service around a databaseHow to – wrap soap web service around a database
How to – wrap soap web service around a databaseSon Nguyen
 
SpringBootCompleteBootcamp.pptx
SpringBootCompleteBootcamp.pptxSpringBootCompleteBootcamp.pptx
SpringBootCompleteBootcamp.pptxSUFYAN SATTAR
 

Ähnlich wie Building Your First App with MongoDB (20)

IBM Integration Bus and REST APIs - Sanjay Nagchowdhury
IBM Integration Bus and REST APIs - Sanjay NagchowdhuryIBM Integration Bus and REST APIs - Sanjay Nagchowdhury
IBM Integration Bus and REST APIs - Sanjay Nagchowdhury
 
MongoDB Days UK: Building Apps with the MEAN Stack
MongoDB Days UK: Building Apps with the MEAN StackMongoDB Days UK: Building Apps with the MEAN Stack
MongoDB Days UK: Building Apps with the MEAN Stack
 
RESTful API-centric Universe
RESTful API-centric UniverseRESTful API-centric Universe
RESTful API-centric Universe
 
ASP.NET Mvc 4 web api
ASP.NET Mvc 4 web apiASP.NET Mvc 4 web api
ASP.NET Mvc 4 web api
 
Hia 1691-using iib-to_support_api_economy
Hia 1691-using iib-to_support_api_economyHia 1691-using iib-to_support_api_economy
Hia 1691-using iib-to_support_api_economy
 
REST APIs
REST APIsREST APIs
REST APIs
 
Switch to Backend 2023
Switch to Backend 2023Switch to Backend 2023
Switch to Backend 2023
 
Basic API Creation with Node.JS
Basic API Creation with Node.JSBasic API Creation with Node.JS
Basic API Creation with Node.JS
 
Resting on your laurels will get you powned
Resting on your laurels will get you pownedResting on your laurels will get you powned
Resting on your laurels will get you powned
 
Databasecentricapisonthecloudusingplsqlandnodejscon3153oow2016 160922021655
Databasecentricapisonthecloudusingplsqlandnodejscon3153oow2016 160922021655Databasecentricapisonthecloudusingplsqlandnodejscon3153oow2016 160922021655
Databasecentricapisonthecloudusingplsqlandnodejscon3153oow2016 160922021655
 
REST API 20.2 - Appworks Gateway Integration.pptx
REST API 20.2 - Appworks Gateway Integration.pptxREST API 20.2 - Appworks Gateway Integration.pptx
REST API 20.2 - Appworks Gateway Integration.pptx
 
Integrate MongoDB & SQL data with a single REST API
Integrate MongoDB & SQL data with a single REST APIIntegrate MongoDB & SQL data with a single REST API
Integrate MongoDB & SQL data with a single REST API
 
Reactive application using meteor
Reactive application using meteorReactive application using meteor
Reactive application using meteor
 
SFScon 2020 - Nikola Milisavljevic - BASE - Python REST API framework
SFScon 2020 - Nikola Milisavljevic - BASE - Python REST API frameworkSFScon 2020 - Nikola Milisavljevic - BASE - Python REST API framework
SFScon 2020 - Nikola Milisavljevic - BASE - Python REST API framework
 
APITalkMeetupSharable
APITalkMeetupSharableAPITalkMeetupSharable
APITalkMeetupSharable
 
MSWD:MERN STACK WEB DEVELOPMENT COURSE CODE
MSWD:MERN STACK WEB DEVELOPMENT COURSE CODEMSWD:MERN STACK WEB DEVELOPMENT COURSE CODE
MSWD:MERN STACK WEB DEVELOPMENT COURSE CODE
 
Sec presentation
Sec presentationSec presentation
Sec presentation
 
(ATS6-PLAT04) Query service
(ATS6-PLAT04) Query service (ATS6-PLAT04) Query service
(ATS6-PLAT04) Query service
 
How to – wrap soap web service around a database
How to – wrap soap web service around a databaseHow to – wrap soap web service around a database
How to – wrap soap web service around a database
 
SpringBootCompleteBootcamp.pptx
SpringBootCompleteBootcamp.pptxSpringBootCompleteBootcamp.pptx
SpringBootCompleteBootcamp.pptx
 

Mehr von MongoDB

MongoDB SoCal 2020: Migrate Anything* to MongoDB Atlas
MongoDB SoCal 2020: Migrate Anything* to MongoDB AtlasMongoDB SoCal 2020: Migrate Anything* to MongoDB Atlas
MongoDB SoCal 2020: Migrate Anything* to MongoDB AtlasMongoDB
 
MongoDB SoCal 2020: Go on a Data Safari with MongoDB Charts!
MongoDB SoCal 2020: Go on a Data Safari with MongoDB Charts!MongoDB SoCal 2020: Go on a Data Safari with MongoDB Charts!
MongoDB SoCal 2020: Go on a Data Safari with MongoDB Charts!MongoDB
 
MongoDB SoCal 2020: Using MongoDB Services in Kubernetes: Any Platform, Devel...
MongoDB SoCal 2020: Using MongoDB Services in Kubernetes: Any Platform, Devel...MongoDB SoCal 2020: Using MongoDB Services in Kubernetes: Any Platform, Devel...
MongoDB SoCal 2020: Using MongoDB Services in Kubernetes: Any Platform, Devel...MongoDB
 
MongoDB SoCal 2020: A Complete Methodology of Data Modeling for MongoDB
MongoDB SoCal 2020: A Complete Methodology of Data Modeling for MongoDBMongoDB SoCal 2020: A Complete Methodology of Data Modeling for MongoDB
MongoDB SoCal 2020: A Complete Methodology of Data Modeling for MongoDBMongoDB
 
MongoDB SoCal 2020: From Pharmacist to Analyst: Leveraging MongoDB for Real-T...
MongoDB SoCal 2020: From Pharmacist to Analyst: Leveraging MongoDB for Real-T...MongoDB SoCal 2020: From Pharmacist to Analyst: Leveraging MongoDB for Real-T...
MongoDB SoCal 2020: From Pharmacist to Analyst: Leveraging MongoDB for Real-T...MongoDB
 
MongoDB SoCal 2020: Best Practices for Working with IoT and Time-series Data
MongoDB SoCal 2020: Best Practices for Working with IoT and Time-series DataMongoDB SoCal 2020: Best Practices for Working with IoT and Time-series Data
MongoDB SoCal 2020: Best Practices for Working with IoT and Time-series DataMongoDB
 
MongoDB SoCal 2020: MongoDB Atlas Jump Start
 MongoDB SoCal 2020: MongoDB Atlas Jump Start MongoDB SoCal 2020: MongoDB Atlas Jump Start
MongoDB SoCal 2020: MongoDB Atlas Jump StartMongoDB
 
MongoDB .local San Francisco 2020: Powering the new age data demands [Infosys]
MongoDB .local San Francisco 2020: Powering the new age data demands [Infosys]MongoDB .local San Francisco 2020: Powering the new age data demands [Infosys]
MongoDB .local San Francisco 2020: Powering the new age data demands [Infosys]MongoDB
 
MongoDB .local San Francisco 2020: Using Client Side Encryption in MongoDB 4.2
MongoDB .local San Francisco 2020: Using Client Side Encryption in MongoDB 4.2MongoDB .local San Francisco 2020: Using Client Side Encryption in MongoDB 4.2
MongoDB .local San Francisco 2020: Using Client Side Encryption in MongoDB 4.2MongoDB
 
MongoDB .local San Francisco 2020: Using MongoDB Services in Kubernetes: any ...
MongoDB .local San Francisco 2020: Using MongoDB Services in Kubernetes: any ...MongoDB .local San Francisco 2020: Using MongoDB Services in Kubernetes: any ...
MongoDB .local San Francisco 2020: Using MongoDB Services in Kubernetes: any ...MongoDB
 
MongoDB .local San Francisco 2020: Go on a Data Safari with MongoDB Charts!
MongoDB .local San Francisco 2020: Go on a Data Safari with MongoDB Charts!MongoDB .local San Francisco 2020: Go on a Data Safari with MongoDB Charts!
MongoDB .local San Francisco 2020: Go on a Data Safari with MongoDB Charts!MongoDB
 
MongoDB .local San Francisco 2020: From SQL to NoSQL -- Changing Your Mindset
MongoDB .local San Francisco 2020: From SQL to NoSQL -- Changing Your MindsetMongoDB .local San Francisco 2020: From SQL to NoSQL -- Changing Your Mindset
MongoDB .local San Francisco 2020: From SQL to NoSQL -- Changing Your MindsetMongoDB
 
MongoDB .local San Francisco 2020: MongoDB Atlas Jumpstart
MongoDB .local San Francisco 2020: MongoDB Atlas JumpstartMongoDB .local San Francisco 2020: MongoDB Atlas Jumpstart
MongoDB .local San Francisco 2020: MongoDB Atlas JumpstartMongoDB
 
MongoDB .local San Francisco 2020: Tips and Tricks++ for Querying and Indexin...
MongoDB .local San Francisco 2020: Tips and Tricks++ for Querying and Indexin...MongoDB .local San Francisco 2020: Tips and Tricks++ for Querying and Indexin...
MongoDB .local San Francisco 2020: Tips and Tricks++ for Querying and Indexin...MongoDB
 
MongoDB .local San Francisco 2020: Aggregation Pipeline Power++
MongoDB .local San Francisco 2020: Aggregation Pipeline Power++MongoDB .local San Francisco 2020: Aggregation Pipeline Power++
MongoDB .local San Francisco 2020: Aggregation Pipeline Power++MongoDB
 
MongoDB .local San Francisco 2020: A Complete Methodology of Data Modeling fo...
MongoDB .local San Francisco 2020: A Complete Methodology of Data Modeling fo...MongoDB .local San Francisco 2020: A Complete Methodology of Data Modeling fo...
MongoDB .local San Francisco 2020: A Complete Methodology of Data Modeling fo...MongoDB
 
MongoDB .local San Francisco 2020: MongoDB Atlas Data Lake Technical Deep Dive
MongoDB .local San Francisco 2020: MongoDB Atlas Data Lake Technical Deep DiveMongoDB .local San Francisco 2020: MongoDB Atlas Data Lake Technical Deep Dive
MongoDB .local San Francisco 2020: MongoDB Atlas Data Lake Technical Deep DiveMongoDB
 
MongoDB .local San Francisco 2020: Developing Alexa Skills with MongoDB & Golang
MongoDB .local San Francisco 2020: Developing Alexa Skills with MongoDB & GolangMongoDB .local San Francisco 2020: Developing Alexa Skills with MongoDB & Golang
MongoDB .local San Francisco 2020: Developing Alexa Skills with MongoDB & GolangMongoDB
 
MongoDB .local Paris 2020: Realm : l'ingrédient secret pour de meilleures app...
MongoDB .local Paris 2020: Realm : l'ingrédient secret pour de meilleures app...MongoDB .local Paris 2020: Realm : l'ingrédient secret pour de meilleures app...
MongoDB .local Paris 2020: Realm : l'ingrédient secret pour de meilleures app...MongoDB
 
MongoDB .local Paris 2020: Upply @MongoDB : Upply : Quand le Machine Learning...
MongoDB .local Paris 2020: Upply @MongoDB : Upply : Quand le Machine Learning...MongoDB .local Paris 2020: Upply @MongoDB : Upply : Quand le Machine Learning...
MongoDB .local Paris 2020: Upply @MongoDB : Upply : Quand le Machine Learning...MongoDB
 

Mehr von MongoDB (20)

MongoDB SoCal 2020: Migrate Anything* to MongoDB Atlas
MongoDB SoCal 2020: Migrate Anything* to MongoDB AtlasMongoDB SoCal 2020: Migrate Anything* to MongoDB Atlas
MongoDB SoCal 2020: Migrate Anything* to MongoDB Atlas
 
MongoDB SoCal 2020: Go on a Data Safari with MongoDB Charts!
MongoDB SoCal 2020: Go on a Data Safari with MongoDB Charts!MongoDB SoCal 2020: Go on a Data Safari with MongoDB Charts!
MongoDB SoCal 2020: Go on a Data Safari with MongoDB Charts!
 
MongoDB SoCal 2020: Using MongoDB Services in Kubernetes: Any Platform, Devel...
MongoDB SoCal 2020: Using MongoDB Services in Kubernetes: Any Platform, Devel...MongoDB SoCal 2020: Using MongoDB Services in Kubernetes: Any Platform, Devel...
MongoDB SoCal 2020: Using MongoDB Services in Kubernetes: Any Platform, Devel...
 
MongoDB SoCal 2020: A Complete Methodology of Data Modeling for MongoDB
MongoDB SoCal 2020: A Complete Methodology of Data Modeling for MongoDBMongoDB SoCal 2020: A Complete Methodology of Data Modeling for MongoDB
MongoDB SoCal 2020: A Complete Methodology of Data Modeling for MongoDB
 
MongoDB SoCal 2020: From Pharmacist to Analyst: Leveraging MongoDB for Real-T...
MongoDB SoCal 2020: From Pharmacist to Analyst: Leveraging MongoDB for Real-T...MongoDB SoCal 2020: From Pharmacist to Analyst: Leveraging MongoDB for Real-T...
MongoDB SoCal 2020: From Pharmacist to Analyst: Leveraging MongoDB for Real-T...
 
MongoDB SoCal 2020: Best Practices for Working with IoT and Time-series Data
MongoDB SoCal 2020: Best Practices for Working with IoT and Time-series DataMongoDB SoCal 2020: Best Practices for Working with IoT and Time-series Data
MongoDB SoCal 2020: Best Practices for Working with IoT and Time-series Data
 
MongoDB SoCal 2020: MongoDB Atlas Jump Start
 MongoDB SoCal 2020: MongoDB Atlas Jump Start MongoDB SoCal 2020: MongoDB Atlas Jump Start
MongoDB SoCal 2020: MongoDB Atlas Jump Start
 
MongoDB .local San Francisco 2020: Powering the new age data demands [Infosys]
MongoDB .local San Francisco 2020: Powering the new age data demands [Infosys]MongoDB .local San Francisco 2020: Powering the new age data demands [Infosys]
MongoDB .local San Francisco 2020: Powering the new age data demands [Infosys]
 
MongoDB .local San Francisco 2020: Using Client Side Encryption in MongoDB 4.2
MongoDB .local San Francisco 2020: Using Client Side Encryption in MongoDB 4.2MongoDB .local San Francisco 2020: Using Client Side Encryption in MongoDB 4.2
MongoDB .local San Francisco 2020: Using Client Side Encryption in MongoDB 4.2
 
MongoDB .local San Francisco 2020: Using MongoDB Services in Kubernetes: any ...
MongoDB .local San Francisco 2020: Using MongoDB Services in Kubernetes: any ...MongoDB .local San Francisco 2020: Using MongoDB Services in Kubernetes: any ...
MongoDB .local San Francisco 2020: Using MongoDB Services in Kubernetes: any ...
 
MongoDB .local San Francisco 2020: Go on a Data Safari with MongoDB Charts!
MongoDB .local San Francisco 2020: Go on a Data Safari with MongoDB Charts!MongoDB .local San Francisco 2020: Go on a Data Safari with MongoDB Charts!
MongoDB .local San Francisco 2020: Go on a Data Safari with MongoDB Charts!
 
MongoDB .local San Francisco 2020: From SQL to NoSQL -- Changing Your Mindset
MongoDB .local San Francisco 2020: From SQL to NoSQL -- Changing Your MindsetMongoDB .local San Francisco 2020: From SQL to NoSQL -- Changing Your Mindset
MongoDB .local San Francisco 2020: From SQL to NoSQL -- Changing Your Mindset
 
MongoDB .local San Francisco 2020: MongoDB Atlas Jumpstart
MongoDB .local San Francisco 2020: MongoDB Atlas JumpstartMongoDB .local San Francisco 2020: MongoDB Atlas Jumpstart
MongoDB .local San Francisco 2020: MongoDB Atlas Jumpstart
 
MongoDB .local San Francisco 2020: Tips and Tricks++ for Querying and Indexin...
MongoDB .local San Francisco 2020: Tips and Tricks++ for Querying and Indexin...MongoDB .local San Francisco 2020: Tips and Tricks++ for Querying and Indexin...
MongoDB .local San Francisco 2020: Tips and Tricks++ for Querying and Indexin...
 
MongoDB .local San Francisco 2020: Aggregation Pipeline Power++
MongoDB .local San Francisco 2020: Aggregation Pipeline Power++MongoDB .local San Francisco 2020: Aggregation Pipeline Power++
MongoDB .local San Francisco 2020: Aggregation Pipeline Power++
 
MongoDB .local San Francisco 2020: A Complete Methodology of Data Modeling fo...
MongoDB .local San Francisco 2020: A Complete Methodology of Data Modeling fo...MongoDB .local San Francisco 2020: A Complete Methodology of Data Modeling fo...
MongoDB .local San Francisco 2020: A Complete Methodology of Data Modeling fo...
 
MongoDB .local San Francisco 2020: MongoDB Atlas Data Lake Technical Deep Dive
MongoDB .local San Francisco 2020: MongoDB Atlas Data Lake Technical Deep DiveMongoDB .local San Francisco 2020: MongoDB Atlas Data Lake Technical Deep Dive
MongoDB .local San Francisco 2020: MongoDB Atlas Data Lake Technical Deep Dive
 
MongoDB .local San Francisco 2020: Developing Alexa Skills with MongoDB & Golang
MongoDB .local San Francisco 2020: Developing Alexa Skills with MongoDB & GolangMongoDB .local San Francisco 2020: Developing Alexa Skills with MongoDB & Golang
MongoDB .local San Francisco 2020: Developing Alexa Skills with MongoDB & Golang
 
MongoDB .local Paris 2020: Realm : l'ingrédient secret pour de meilleures app...
MongoDB .local Paris 2020: Realm : l'ingrédient secret pour de meilleures app...MongoDB .local Paris 2020: Realm : l'ingrédient secret pour de meilleures app...
MongoDB .local Paris 2020: Realm : l'ingrédient secret pour de meilleures app...
 
MongoDB .local Paris 2020: Upply @MongoDB : Upply : Quand le Machine Learning...
MongoDB .local Paris 2020: Upply @MongoDB : Upply : Quand le Machine Learning...MongoDB .local Paris 2020: Upply @MongoDB : Upply : Quand le Machine Learning...
MongoDB .local Paris 2020: Upply @MongoDB : Upply : Quand le Machine Learning...
 

Kürzlich hochgeladen

Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)wesley chun
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘RTylerCroy
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processorsdebabhi2
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Servicegiselly40
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024The Digital Insurer
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...Neo4j
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...Martijn de Jong
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?Igalia
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsMaria Levchenko
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CVKhem
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerThousandEyes
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...apidays
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationMichael W. Hawkins
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024Rafal Los
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonetsnaman860154
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Miguel Araújo
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking MenDelhi Call girls
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreternaman860154
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityPrincipled Technologies
 

Kürzlich hochgeladen (20)

Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)Powerful Google developer tools for immediate impact! (2023-24 C)
Powerful Google developer tools for immediate impact! (2023-24 C)
 
🐬 The future of MySQL is Postgres 🐘
🐬  The future of MySQL is Postgres   🐘🐬  The future of MySQL is Postgres   🐘
🐬 The future of MySQL is Postgres 🐘
 
Exploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone ProcessorsExploring the Future Potential of AI-Enabled Smartphone Processors
Exploring the Future Potential of AI-Enabled Smartphone Processors
 
CNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of ServiceCNv6 Instructor Chapter 6 Quality of Service
CNv6 Instructor Chapter 6 Quality of Service
 
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
Bajaj Allianz Life Insurance Company - Insurer Innovation Award 2024
 
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...Workshop - Best of Both Worlds_ Combine  KG and Vector search for  enhanced R...
Workshop - Best of Both Worlds_ Combine KG and Vector search for enhanced R...
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?A Year of the Servo Reboot: Where Are We Now?
A Year of the Servo Reboot: Where Are We Now?
 
Handwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed textsHandwritten Text Recognition for manuscripts and early printed texts
Handwritten Text Recognition for manuscripts and early printed texts
 
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law DevelopmentsTrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
TrustArc Webinar - Stay Ahead of US State Data Privacy Law Developments
 
Real Time Object Detection Using Open CV
Real Time Object Detection Using Open CVReal Time Object Detection Using Open CV
Real Time Object Detection Using Open CV
 
How to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected WorkerHow to Troubleshoot Apps for the Modern Connected Worker
How to Troubleshoot Apps for the Modern Connected Worker
 
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
Apidays Singapore 2024 - Building Digital Trust in a Digital Economy by Veron...
 
GenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day PresentationGenCyber Cyber Security Day Presentation
GenCyber Cyber Security Day Presentation
 
The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024The 7 Things I Know About Cyber Security After 25 Years | April 2024
The 7 Things I Know About Cyber Security After 25 Years | April 2024
 
How to convert PDF to text with Nanonets
How to convert PDF to text with NanonetsHow to convert PDF to text with Nanonets
How to convert PDF to text with Nanonets
 
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
Mastering MySQL Database Architecture: Deep Dive into MySQL Shell and MySQL R...
 
08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men08448380779 Call Girls In Civil Lines Women Seeking Men
08448380779 Call Girls In Civil Lines Women Seeking Men
 
Presentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreterPresentation on how to chat with PDF using ChatGPT code interpreter
Presentation on how to chat with PDF using ChatGPT code interpreter
 
Boost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivityBoost PC performance: How more available memory can improve productivity
Boost PC performance: How more available memory can improve productivity
 

Building Your First App with MongoDB

  • 1. Build an application with MongoDB Part 1: Creating a REST API using the ME(a)N stack Chad Tindel Senior Solution Architect @ctindel
  • 2. 2 What is all this stuff?
  • 3. 3 • Introduction to the MEAN Stack • What is a REST API? • Creating our REST API • Defining our Data Model • Real-life authentication using Stormpath • Javascript Quirks • WRITE YOUR TESTS FIRST • Let’s look at some application code Agenda
  • 5. 5 • M = MongoDB/Mongoose.js, the most popular nosql operational database • E = Express.js, a lightweight web application framework • A = Angular.js, a robust framework for creating HTML5 and Javascript rich web applications • N = Node.js, a server-side javascript interpreter The MEAN Stack A modern replacement for LAMP
  • 6. What is a REST API?
  • 7. 7 • REST = “Representation State Transfer” • Essentially it’s just a lighter weight, though not- standardized, alternative to SOAP and WSDL XML- based API protocols • Uses a client-server model, where the server is actually an HTTP server • Client sends HTTP verbs (GET, POST, PUT, DELETE) along with a URL and variable parameters that are urlencoded • The URL tells us what object to act on • Server replies with a result code and valid JSON What is a REST API?
  • 8. 8 • GET – When a client wants to read an object. • POST – Went a client wants to insert/create an object. • PUT – When a client wants to update an object. • DELETE – When a client wants to delete an object HTTP Verbs – Mapping to CRUD
  • 9. 9 • Some common codes we might use – 200 – “OK” – 201 – “Created” (Used with POST) – 400 – “Bad Request” (Perhaps missing required parameters) – 401 – “Unauthorized” (Missing authentication parameters) – 403 – “Forbidden” (You were authenticated but lacking required privileges) – 404 – “Not Found” • http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html HTTP Result Codes
  • 10. 10 • Things you might want to say to me me at this point: – “REST APIs aren’t sexy” – “How am I supposed to show this off to my boss?” – “My clients wants to see a fancy website or mobile app” • REST APIs are a way for you to create a data service enabling you to easily create all your other applications – HTML5 / Javascript – Android – iOS Why are we starting with a REST API?
  • 11. 11 • Because all the VC Money is in creating apps that are So-Lo-Mo-Co, lots of new startups don’t even have a web interface, such as: – Uber – WhatsApp – Postmates – Wash.io • Creating a REST API also allows other companies/applications to easily plug-in to your application as well, turning your application into a platform and making it more powerful New companies don’t have an HTML Interface
  • 13. 13 • We’ll be building an RSS Aggregation application, similar to our dearly departed Google Reader • Our application today will have two components – The REST API – The Feed Grabber • Since the point of today’s talk is to learn about creating a REST API and not the intricacies of RSS feeds, we won’t be discussing the feed grabber Let’s build an application!
  • 14. 14 • We’ll need to define data models for and store the following data: – Users – RSS Feeds – Feed Entries – User Feed Subscriptions – Which feed entries a user has already read • We’ll need to allow users to: – Create an account – Subscribe/unsubscribe to feeds – Read feed entries – Mark feeds/entries as read or unread Let’s build an application! Data Models
  • 15. 15 { "_id" : ObjectId("523b1153a2aa6a3233a913f8"), "requiresAuthentication" : false, "modifiedDate" : ISODate("2014-08-29T17:40:22Z"), "permanentlyRemoved" : false, "feedURL" : "http://feeds.feedburner.com/eater/nyc", "title" : "Eater NY", "bozoBitSet" : false, "enabled" : true, "etag" : "4bL78iLSZud2iXd/vd10mYC32BE", "link" : "http://ny.eater.com/", "permanentRedirectURL" : null, "description" : "The New York City Restaurant, Bar, and Nightlife Blog” } Data Model Design Feed Collection
  • 16. 16 { "_id" : ObjectId("523b1153a2aa6a3233a91412"), "description" : "Buzzfeed asked a bunch of people…”, "title" : "Cronut Mania: Buzzfeed asked a bunch of people...", "summary" : "Buzzfeed asked a bunch of people that were…”, "content" : [ { "base" : "http://ny.eater.com/", "type" : "text/html", "value" : ”LOTS OF HTML HERE", "language" : "en" } ], "entryID" : "tag:ny.eater.com,2013://4.560508", "publishedDate" : ISODate("2013-09-17T20:45:20Z"), "link" : "http://ny.eater.com/archives/2013/09/cronut_mania_41.php", "feedID" : ObjectId("523b1153a2aa6a3233a913f8") } Data Model Design Feed Entry Collection
  • 17. 17 { "_id" : ObjectId("54ad6c3ae764de42070b27b1"), "active" : true, "email" : "testuser1@example.com", "firstName" : "Test", "lastName" : "User1", "sp_api_key_id" : "6YQB0A8VXM0X8RVDPPLRHBI7J", "sp_api_key_secret" : "veBw/YFx56Dl0bbiVEpvbjF”, "lastLogin" : ISODate("2015-01-07T17:26:18.996Z"), "created" : ISODate("2015-01-07T17:26:18.995Z"), "subs" : [ ObjectId("523b1153a2aa6a3233a913f8"), ObjectId("54b563c3a50a190b50f4d63b")], } Data Model Design User Collection
  • 18. 18 { "_id" : ObjectId("523b2fcc054b1b8c579bdb82"), "read" : true, "user_id" : ObjectId("54ad6c3ae764de42070b27b1"), "feed_entry_id" : ObjectId("523b1153a2aa6a3233a91412"), "feed_id" : ObjectId("523b1153a2aa6a3233a913f8") } Data Model Design User-Feed-Entry Mapping Collection
  • 19. 19 • We’ll need to allow users to: – Create an account – Subscribe/unsubscribe to feeds – Read feed entries – Mark feeds/entries as read or unread Let’s build an application! User Actions
  • 20. 20 Creating our REST API Route Verb Description Variables /user/enroll POST Register a new user firstName lastName email password /user/resetPassword PUT Password Reset email /feeds GET Get feed subscriptions for each user with description and unread count /feeds/subscribe PUT Subscribe to a new feed feedURL
  • 21. 21 Creating our REST API Route Verb Description Variables /feeds/entries GET Get all entries for feeds the user is subscribed to /feeds/<feedid>/entries GET Get all entries for a specific feed /feeds/<feedid> PUT Mark all entries for a specific feed as read or unread read = <true | false>
  • 22. 22 Creating our REST API Route Verb Description Variables /feeds/<feedid>/entries/<entryid> PUT Mark a specific entry as either read or unread read = <true | false> /feeds/<feedid> DELETE Unsubscribe from this particular feed
  • 23. Real Life Authentication with Stormpath
  • 24. 24 Using Stormpath for Authentication • “User Management as a Service” – Authentication – Authorization – API Keys • REST JSON API + – Node SDK – Express Plugin – Passport Plugin
  • 25. 25 Using Stormpath for Authentication • Stormpath will give us a secret key for each “Application” we define with them. These applications can be “Reader Prod”, “Reader Test”, etc. • Stormpath will give us an API Key Properties file as well • We can define password strength requirements for each application, like – Must have >= 8 characters – Must include lowercase and uppercase – Must include a number – Must include a non-alphabetic character • Stormpath keeps track of all of our users and assigns them API Keys which we can use for our REST API Authentication
  • 27. 27 Creating a Node.js Application • Install node.js – http://nodejs.org/download/ • Node.js applications are built using a lot of library modules • You define a package.json file describing your application and all of it’s library dependencies • You use the Node.js Package Manager to install a copy of those libraries in a subdirectory of your application (node_modules/) instead of a system directly (like /usr/lib) to avoid the problem of different apps needing different and conflicting library versions • Run “npm install” and it will create the node_modules/ with all of your required libraries
  • 28. 28 Our package.json { "name": "reader-api", "main": "server.js", "dependencies": { "express" : "~4.10.0", "stormpath" : "~0.7.5", "express-stormpath" : "~0.5.9", "mongodb" : "~1.4.26”, "mongoose" : "~3.8.0", "body-parser" : "~1.10.0”, "method-override" : "~2.3.0", "morgan" : "~1.5.0”, "winston" : "~0.8.3”, "express-winston" : "~0.2.9", "validator" : "~3.27.0", "path" : "~0.4.9", "errorhandler" : "~1.3.0", "frisby" : "~0.8.3", "jasmine-node" : "~1.14.5", "async" : "~0.9.0" } }
  • 29. 29 Async Code in Javascript function foo() { someAsyncFunction(params, function(err, results) { console.log(“one”); }); console.log(“two”); } At first glance you might expect the output to be: one two But actually it’s the reverse because the line that prints “one” happens later, asynchronously, in the callback
  • 30. 30 Async Library https://github.com/caolan/async actionArray = [ function one(cb) { someAsyncFunction(params, function(err, results) { if (err) { cb(new Error(“There was an error”)); } console.log(“one”); cb(null); }); }, function two(cb) { console.log(“two”); cb(null); }] ] Async.series(actionArray);
  • 32. 32 Defining some utility libraries test/config/test_config.js module.exports = { url : 'http://localhost:8000/api/v1.0' }
  • 33. 33 Defining some utility libraries test/setup_tests.js function connectDB(callback) { mongoClient.connect(dbConfig.testDBURL, function(err, db) { assert.equal(null, err); reader_test_db = db; console.log("Connected correctly to server"); callback(0); }); }
  • 34. 34 Defining some utility libraries test/setup_tests.js (continued) function dropUserCollection(callback) { console.log("dropUserCollection"); user = reader_test_db.collection('user'); if (undefined != user) { user.drop(function(err, reply) { console.log('user collection dropped'); callback(0); }); } else { callback(0); } },
  • 35. 35 Defining some utility libraries test/setup_tests.js (continued) function dropUserFeedEntryCollection(callback) { console.log("dropUserFeedEntryCollection"); user_feed_entry = reader_test_db.collection('user_feed_entry'); if (undefined != user_feed_entry) { user_feed_entry.drop(function(err, reply) { console.log('user_feed_entry collection dropped'); callback(0); }); } else { callback(0); } }
  • 36. 36 Defining some utility libraries test/setup_tests.js (continued) function getApplication(callback) { console.log("getApplication"); client.getApplications({name: SP_APP_NAME}, function(err, applications) { console.log(applications); if (err) { log("Error in getApplications"); throw err; } app = applications.items[0]; callback(0); }); },
  • 37. 37 Defining some utility libraries test/setup_tests.js (continued) function deleteTestAccounts(callback) { app.getAccounts({email: TU_EMAIL_REGEX}, function(err, accounts) { if (err) throw err; accounts.items.forEach(function deleteAccount(account) { account.delete(function deleteError(err) { if (err) throw err; }); }); callback(0); }); } function closeDB(callback) { reader_test_db.close(); } async.series([connectDB, dropUserCollection, dropUserFeedEntryCollection, dropUserFeedEntryCollection, getApplication, deleteTestAccounts, closeDB);
  • 38. 38 Using frisby.js to define test cases test/create_accounts_error_spec.js TU1_FN = "Test"; TU1_LN = "User1"; TU1_EMAIL = "testuser1@example.com"; TU1_PW = "testUser123"; TU_EMAIL_REGEX = 'testuser*'; SP_APP_NAME = 'Reader Test'; var frisby = require('frisby'); var tc = require('./config/test_config'); frisby.create('POST missing firstName') .post(tc.url + '/user/enroll', { 'lastName' : TU1_LN, 'email' : TU1_EMAIL, 'password' : TU1_PW }) .expectStatus(400) .expectHeader('Content-Type', 'application/json; charset=utf-8') .expectJSON({'error' : 'Undefined First Name'}) .toss()
  • 39. 39 Using frisby.js to define test cases test/create_accounts_error_spec.js (continued) frisby.create('POST password missing lowercase') .post(tc.url + '/user/enroll', { 'firstName' : TU1_FN, 'lastName' : TU1_LN, 'email' : TU1_EMAIL, 'password' : 'TESTUSER123' }) .expectStatus(400) .expectHeader('Content-Type', 'application/json; charset=utf-8') .expectJSONTypes({'error' : String}) .toss()
  • 40. 40 Using frisby.js to define test cases test/create_accounts_error_spec.js (continued) frisby.create('POST invalid email address') .post(tc.url + '/user/enroll', { 'firstName' : TU1_FN, 'lastName' : TU1_LN, 'email' : "invalid.email", 'password' : 'testUser' }) .expectStatus(400) .expectHeader('Content-Type', 'application/json; charset=utf-8') .expectJSONTypes({'error' : String}) .toss()
  • 41. 41 Using frisby.js to define test cases test/create_accounts_spec.js TEST_USERS = [{'fn' : 'Test', 'ln' : 'User1', 'email' : 'testuser1@example.com', 'pwd' : 'testUser123'}, {'fn' : 'Test', 'ln' : 'User2', 'email' : 'testuser2@example.com', 'pwd' : 'testUser123'}, {'fn' : 'Test', 'ln' : 'User3', 'email' : 'testuser3@example.com', 'pwd' : 'testUser123'}] SP_APP_NAME = 'Reader Test'; var frisby = require('frisby'); var tc = require('./config/test_config');
  • 42. 42 Using frisby.js to define test cases test/create_accounts_spec.js (continued) TEST_USERS.forEach(function createUser(user, index, array) { frisby.create('POST enroll user ' + user.email) .post(tc.url + '/user/enroll', { 'firstName' : user.fn, 'lastName' : user.ln, 'email' : user.email, 'password' : user.pwd }) .expectStatus(201) .expectHeader('Content-Type', 'application/json; charset=utf-8') .expectJSON({ 'firstName' : user.fn, 'lastName' : user.ln, 'email' : user.email }) .toss() });
  • 43. 43 Using frisby.js to define test cases test/create_accounts_spec.js (continued) frisby.create('POST enroll duplicate user ') .post(tc.url + '/user/enroll', { 'firstName' : TEST_USERS[0].fn, 'lastName' : TEST_USERS[0].ln, 'email' : TEST_USERS[0].email, 'password' : TEST_USERS[0].pwd }) .expectStatus(400) .expectHeader('Content-Type', 'application/json; charset=utf-8') .expectJSON({'error' : 'Account with that email already exists. Please choose another email.'}) .toss()
  • 44. 44 Using frisby.js to define test cases Need to create /tmp/readerTestCreds.js We want to dynamically create a file that looks like this for us to use in defining test cases that require us to authenticate a user: TEST_USERS = [{ "_id":"54ad6c3ae764de42070b27b1", "email":"testuser1@example.com", "firstName":"Test", "lastName":"User1", "sp_api_key_id":”<API KEY ID>", "sp_api_key_secret":”<API KEY SECRET>” }, { "_id":"54ad6c3be764de42070b27b2”, "email":"testuser2@example.com", "firstName":"Test", "lastName":"User2”, "sp_api_key_id":”<API KEY ID>", "sp_api_key_secret":”<API KEY SECRET>” }]; module.exports = TEST_USERS;
  • 45. 45 Using frisby.js to define test cases tests/writeCreds.js TU_EMAIL_REGEX = new RegExp('^testuser*'); SP_APP_NAME = 'Reader Test'; TEST_CREDS_TMP_FILE = '/tmp/readerTestCreds.js'; var async = require('async'); var dbConfig = require('./config/db.js'); var mongodb = require('mongodb'); assert = require('assert'); var mongoClient = mongodb.MongoClient var reader_test_db = null; var users_array = null;
  • 46. 46 Using frisby.js to define test cases tests/writeCreds.js (continued) function connectDB(callback) { mongoClient.connect(dbConfig.testDBURL, function(err, db) { assert.equal(null, err); reader_test_db = db; callback(null); }); } function lookupUserKeys(callback) { console.log("lookupUserKeys"); user_coll = reader_test_db.collection('user'); user_coll.find({email : TU_EMAIL_REGEX}).toArray(function(err, users) { users_array = users; callback(null); }); }
  • 47. 47 Using frisby.js to define test cases tests/writeCreds.js (continued) function writeCreds(callback) { var fs = require('fs'); fs.writeFileSync(TEST_CREDS_TMP_FILE, 'TEST_USERS = '); fs.appendFileSync(TEST_CREDS_TMP_FILE, JSON.stringify(users_array)); fs.appendFileSync(TEST_CREDS_TMP_FILE, '; module.exports = TEST_USERS;'); callback(0); } function closeDB(callback) { reader_test_db.close(); } async.series([connectDB, lookupUserKeys, writeCreds, closeDB]);
  • 48. 48 Using frisby.js to define test cases tests/feed_spec.js TEST_USERS = require('/tmp/readerTestCreds.js'); var frisby = require('frisby'); var tc = require('./config/test_config'); var async = require('async'); var dbConfig = require('./config/db.js'); var dilbertFeedURL = 'http://feeds.feedburner.com/DilbertDailyStrip'; var nycEaterFeedURL = 'http://feeds.feedburner.com/eater/nyc'; function addEmptyFeedListTest(callback) { var user = TEST_USERS[0]; frisby.create('GET empty feed list for user ' + user.email) .get(tc.url + '/feeds') .auth(user.sp_api_key_id, user.sp_api_key_secret) .expectStatus(200) .expectHeader('Content-Type', 'application/json; charset=utf-8') .expectJSON({feeds : []}) .toss() callback(null); }
  • 49. 49 Using frisby.js to define test cases tests/feed_spec.js function subOneFeed(callback) { var user = TEST_USERS[0]; frisby.create('PUT Add feed sub for user ' + user.email) .put(tc.url + '/feeds/subscribe', {'feedURL' : dilbertFeedURL}) .auth(user.sp_api_key_id, user.sp_api_key_secret) .expectStatus(201) .expectHeader('Content-Type', 'application/json; charset=utf-8') .expectJSONLength('user.subs', 1) .toss() callback(null); }
  • 50. 50 Using frisby.js to define test cases tests/feed_spec.js function subDuplicateFeed(callback) { var user = TEST_USERS[0]; frisby.create('PUT Add duplicate feed sub for user ' + user.email) .put(tc.url + '/feeds/subscribe', {'feedURL' : dilbertFeedURL}) .auth(user.sp_api_key_id, user.sp_api_key_secret) .expectStatus(201) .expectHeader('Content-Type', 'application/json; charset=utf-8') .expectJSONLength('user.subs', 1) .toss() callback(null); }
  • 51. 51 Using frisby.js to define test cases tests/feed_spec.js function subSecondFeed(callback) { var user = TEST_USERS[0]; frisby.create('PUT Add second feed sub for user ' + user.email) .put(tc.url + '/feeds/subscribe', {'feedURL' : nycEaterFeedURL}) .auth(user.sp_api_key_id, user.sp_api_key_secret) .expectStatus(201) .expectHeader('Content-Type', 'application/json; charset=utf-8') .expectJSONLength('user.subs', 2) .toss() callback(null); }
  • 52. 52 Using frisby.js to define test cases tests/feed_spec.js function subOneFeedSecondUser(callback) { var user = TEST_USERS[1]; frisby.create('PUT Add one feed sub for second user ' + user.email) .put(tc.url + '/feeds/subscribe', {'feedURL' : nycEaterFeedURL}) .auth(user.sp_api_key_id, user.sp_api_key_secret) .expectStatus(201) .expectHeader('Content-Type', 'application/json; charset=utf-8') .expectJSONLength('user.subs', 1) .toss() callback(null); } async.series([addEmptyFeedListTest, subOneFeed, subDuplicateFeed, subSecondFeed, subOneFeedSecondUser]);
  • 53. Can we FINALLY build our REST API code?
  • 54. 54 Defining some utility libraries config/db.js module.exports = { url : 'mongodb://localhost/reader_test' } // If we wanted to have different database URLs for Dev/QA/Prod we could have // those here
  • 55. 55 Defining some utility libraries config/security.js module.exports = { stormpath_secret_key : ‘YOUR STORMPATH APPLICATION KEY’; } // If we wanted to turn on database authentication we could put that here // This file will NOT get checked into source code control for obvious reasons
  • 56. 56 Defining some utility libraries config/stormpath_apikey.properties apiKey.id = YOUR STORMPATH API KEY ID apiKey.secret = YOUR STORMPATH API KEY SECRET
  • 57. 57 Express.js Overview • In express.js you create an “application” (app) • That application listens on a particular port for HTTP requests to come in • When requests come in, they pass through a middleware chain – Each link in the middleware chain is given a req (the request) object and a res object (to store the results) – Each link can choose to do work, or pass it to the next link • We add new middleware via app.use() • The main middleware is called our “router”, which looks at the URL and routes each different URL/Verb combo to a specific handler function
  • 58. 58 Creating our application! server.js var express = require('express'); var bodyParser = require('body-parser'); var mongoose = require('mongoose'); var stormpath = require('express-stormpath'); var routes = require("./app/routes"); var db = require('./config/db'); var security = require('./config/security'); var app = express(); var morgan = require('morgan’); app.use(morgan); app.use(stormpath.init(app, { apiKeyFile: './config/stormpath_apikey.properties', application: ‘YOUR SP APPLICATION URL', secretKey: security.stormpath_secret_key })); var port = 8000; mongoose.connect(db.url);
  • 59. 59 Creating our application! server.js (continued) app.use(bodyParser.urlencoded({ extended: true })); routes.addAPIRouter(app, mongoose, stormpath); // Define our own middleware at the end of the chain to handle bad URLs app.use(function(req, res, next){ res.status(404); res.json({ error: 'Invalid URL' }); }); app.listen(port); // shoutout to the user console.log('Magic happens on port ' + port); // expose app exports = module.exports = app;
  • 60. 60 Defining our Mongoose Data Models app/routes.js var userSchema = new mongoose.Schema({ active: Boolean, email: { type: String, trim: true, lowercase: true }, firstName: { type: String, trim: true }, lastName: { type: String, trim: true }, sp_api_key_id: { type: String, trim: true }, sp_api_key_secret: { type: String, trim: true }, subs: { type: [mongoose.Schema.Types.ObjectId], default: [] }, created: { type: Date, default: Date.now }, lastLogin: { type: Date, default: Date.now }, }, { collection: 'user' } ); userSchema.index({email : 1}, {unique:true}); userSchema.index({sp_api_key_id : 1}, {unique:true}); var UserModel = mongoose.model( 'User', userSchema );
  • 61. 61 Defining our Mongoose Data Models app/routes.js (continued) var feedSchema = new mongoose.Schema({ feedURL: { type: String, trim:true }, link: { type: String, trim:true }, description: { type: String, trim:true }, state: { type: String, trim:true, lowercase:true, default: 'new' }, createdDate: { type: Date, default: Date.now }, modifiedDate: { type: Date, default: Date.now }, }, { collection: 'feed' } ); feedSchema.index({feedURL : 1}, {unique:true}); feedSchema.index({link : 1}, {unique:true, sparse:true}); var FeedModel = mongoose.model( 'Feed', feedSchema );
  • 62. 62 Defining our Mongoose Data Models app/routes.js (continued) var feedEntrySchema = new mongoose.Schema({ description: { type: String, trim:true }, title: { type: String, trim:true }, summary: { type: String, trim:true }, entryID: { type: String, trim:true }, publishedDate: { type: Date }, link: { type: String, trim:true }, feedID: { type: mongoose.Schema.Types.ObjectId }, state: { type: String, trim:true, lowercase:true, default: 'new' }, created: { type: Date, default: Date.now }, }, { collection: 'feedEntry' } ); feedEntrySchema.index({entryID : 1}); feedEntrySchema.index({feedID : 1}); var FeedEntryModel = mongoose.model( 'FeedEntry', feedEntrySchema );
  • 63. 63 Defining our Mongoose Data Models app/routes.js (continued) var userFeedEntrySchema = new mongoose.Schema({ userID: { type: mongoose.Schema.Types.ObjectId }, feedEntryID: { type: mongoose.Schema.Types.ObjectId }, feedID: { type: mongoose.Schema.Types.ObjectId }, read : { type: Boolean, default: false }, }, { collection: 'userFeedEntry' } ); userFeedEntrySchema.index({userID : 1, feedID : 1, feedEntryID : 1, read : 1}); var UserFeedEntryModel = mongoose.model('UserFeedEntry', userFeedEntrySchema );
  • 64. 64 Defining our Routes app/routes.js (continued) exports.addAPIRouter = function(app, mongoose, stormpath) { app.get('/*', function(req, res, next) { res.contentType('application/json'); next(); }); app.post('/*', function(req, res, next) { res.contentType('application/json'); next(); }); app.put('/*', function(req, res, next) { res.contentType('application/json'); next(); }); app.delete('/*', function(req, res, next) { res.contentType('application/json'); next(); });
  • 65. 65 Defining our Routes app/routes.js (continued) var router = express.Router(); router.post('/user/enroll', function(req, res) { logger.debug('Router for /user/enroll'); … } router.get('/feeds', stormpath.apiAuthenticationRequired, function(req, res) { logger.debug('Router for /feeds'); … } router.put('/feeds/subscribe', stormpath.apiAuthenticationRequired, function(req, res) { logger.debug('Router for /feeds'); … } app.use('/api/v1.0', router); }
  • 66. 66 Looking at our router code Let’s go look at some real router code at: https://github.com/ctindel/reader/blob/master/api/v1.0/app/routes.js
  • 67. 67 Starting the server and running tests • Make sure your mongodb instance is running – mongod • Install the Node Libraries – npm install • Start the REST API server – node server.js • Run test cases – node setup_tests.js – jasmine-node create_accounts_error_spec.js – jasmine-node create_accounts_spec.js – node write_creds.js – jasmine-node feed_spec.js
  • 68. 68 For More Information Resource Location My github repo github.com/ctindel/reader MongoDB Downloads mongodb.com/download Free Online Training education.mongodb.com Webinars and Events mongodb.com/events White Papers mongodb.com/white-papers Case Studies mongodb.com/customers Presentations mongodb.com/presentations Documentation docs.mongodb.org Additional Info info@mongodb.com Resource Location

Hinweis der Redaktion

  1. If you’ve never done javascript, never used MongoDB, or never built a REST API it is easy to get overwhelmed when faced with the task of pulling it all together. Especially because there isn’t a website that shows you how to do everything. We’ll attempt to break it down into manageable chunks so that each is easy to understand when we pull it all together later in code. This isn’t going to be a detailed discussion of Schema Design, Javascript programming, MongoDB Deployment Technologies. We have in-depth webinars on MongoDB topics that have already been recorded and that will be scheduled in the future.
  2. This webinar will be code and example intensive, but people at all skill levels will have something to learn here.
  3. Today we won’t be using angular as we aren’t building an HTML user interface. We’re building a REST API which has no user interface but could be used to build any kind of interface like a website, or an Android application or an iOS application.
  4. The fact that the server replies with JSON (Javascript Object Notation) makes the MEAN stack particularly well-suited to this task as all the components are in Javascript and MongoDB uses JSON notation to hold its data. We’ll explain what JSON looks like when we start defining our Data Models later in the presentation
  5. Before we dive in, it’s important to review that Javascript code is designed to be asynchronous. So any function which does blocking I/O like reading from a socket or querying a database will take a callback function as the last parameter, and then continue with the control flow, only returning to that callback function once the blocking operation completed.
  6. MongoDB has a traditional hierarchical structure similar to an RDBMS. Our nomenclature is Database->Collection->Document->Key/Value Field Sometimes we embed objects and arrays of objects directly, and sometimes we use a normalized model with mapping tables
  7. This is what JSON looks like (Javascript Object Notation) and is how data is modeled and stored in MongoDB MongoDB has a traditional hierarchical structure similar to an RDBMS. Our nomenclature is Database->Collection->Document->Key/Value Field
  8. MongoDB has a traditional hierarchical structure similar to an RDBMS. Our nomenclature is Database->Collection->Document->Key/Value Field
  9. , and then continue with the control flow, only returning to that callback function once the blocking operation completed.
  10. Before we dive in, it’s important to review that Javascript code is designed to be asynchronous. So any function which does blocking I/O like reading from a socket or querying a database will take a callback function as the last parameter, and then continue with the control flow, only returning to that callback function once the blocking operation completed.
  11. This library is so important to how we do things that it’s worth calling out specially
  12. Before we dive in, it’s important to review that Javascript code is designed to be asynchronous. So any function which does blocking I/O like reading from a socket or querying a database will take a callback function as the last parameter, and then continue with the control flow, only returning to that callback function once the blocking operation completed.
  13. Dynamically creating code on the fly is basically how viruses work. Remember kids, always use your power for good and not for evil.
  14. Note the use of .auth here finally
  15. If you’ll remember our test cases are expecting a return payload with the content type set to “application/json” This code will do it for all requests automatically
  16. If you’ll remember our test cases are expecting a return payload with the content type set to “application/json” This code will do it for all requests automatically Note that our first route doesn’t require authentication but our second two routes do. That’s all it takes to use stormpath!
  17. If you’ll remember our test cases are expecting a return payload with the content type set to “application/json” This code will do it for all requests automatically Note that our first route doesn’t require authentication but our second two routes do. That’s all it takes to use stormpath!