Full Stack Development with Node.js and NoSQL

Preview:

Citation preview

Full Stack Development with Node.js and NoSQLMatthew D. Groves (@mgroves)

Nic Raboy (@nraboy)

Full Stack?

Where am I?

• All Things Open

• Raleigh, North Carolina

• https://allthingsopen.org/

Who am I?

• Nic Raboy Matthew D. Groves

• Developer Advocate for Couchbase

• @mgroves on Twitter

• Podcast and blog: https://crosscuttingconcerns.com

• "I am not an expert, but I am an enthusiast."

–Alan Stevens

Full Stack Development with Node.js and NoSQLMatthew D. Groves (@mgroves)

Nic Raboy (@nraboy)

The Role of a Full-Stack Developer

Client Frontend

Backend

The Breakdown of a Stack

Database

Web Application Authentication Middleware

Mobile IoTDesktop

Client Frontend

Backend

Our Stack

Couchbase

Node.js

Angular

What is Couchbase?

Couchbase: The Complete Database Solution

Lightweight embedded NoSQL database

with full CRUD and query functionality.

Secure web gateway with synchronization,

REST, stream, batch and event APIs for

accessing and synchronizing data over the

web.

Highly scalable, highly available, high

performance NoSQL database server.

Built-in enterprise level security throughout the entire stack includes user authentication, user and role based data access control

(RBAC), secure transport (TLS), and 256-bit AES full database encryption.

Couchbase Lite Sync Gateway Couchbase Server

EMBEDDED DATABASE SYNCHRONIZATION DATABASE SERVER

SECURITY

Couchbase Lite Overview

Cross-platform support for all major

operating systems and platforms

Built native from the ground up

500kb for most platforms

256-bit AES full database encryption

11

Couchbase LiteEmbedded Database

Sync Gateway Overview

Synchronize data between Couchbase

Lite and Couchbase Server

REST, Stream, Batch, and Event APIs

Pluggable authentication

Fine grained user and role based

access control

Elastically scalable in real-time

12

Sync GatewaySynchronization

Couchbase Server Overview

Scale easily to thousands of nodes

Consistent high performance that

supports millions of concurrent users

Flexible JSON data model

24x365 always-on availability

13

Couchbase ServerDatabase Server

The Power of the Flexible JSON Schema

• Ability to store data in

multiple ways

• De-normalized single

document, as opposed to

normalizing data across

multiple table

• Dynamic Schema to add

new values when needed

The Couchbase Node.js SDK

• Uses the high performance Couchbase C library

• Compatible with Node.js frameworks

• Express, Sails, Hapi, Etc.

• Minimal coding

• No database maintenance via code

• No parsing queries via application code

Building Applications with Node.js SDK

//including the Node.js dependencyvar Couchbase = require("couchbase");

//connecting to a Couchbase clustervar cluster = new Couchbase.Cluster("couchbase://localhost");

//opening a bucket in the clustervar myBucket = cluster.openBucket("travel-sample");

//preparing N1qlvar myQuery = Couchbase.N1qlQuery();

//creating and saving a Documentvar document = {

firstname: "Matt",lastname: "Groves"

};myBucket.insert("my-key", document, function (error, result) { });

Node.js

function query(sql, done) {var queryToRun = myQuery.fromString(sql);myBucket.query(queryToRun, function (error, result) {

if (error) {console.log("ERROR: ", error);done(error, null);return;

}done(null, result);return;

});}

Node.js

function query(sql, done) {var queryToRun = myQuery.fromString(sql);myBucket.query(queryToRun, function (error, result) {

if (error) {console.log("ERROR: ", error);done(error, null);return;

}done(null, result);return;

});}

Node.js

function query(sql, done) {var queryToRun = myQuery.fromString(sql);myBucket.query(queryToRun, function (error, result) {

if (error) {console.log("ERROR: ", error);done(error, null);return;

}done(null, result);return;

});}

Node.js

function query(sql, done) {var queryToRun = myQuery.fromString(sql);myBucket.query(queryToRun, function (error, result) {

if (error) {console.log("ERROR: ", error);done(error, null);return;

}done(null, result);return;

});}

Node.js

function query(sql, done) {var queryToRun = myQuery.fromString(sql);myBucket.query(queryToRun, function (error, result) {

if (error) {console.log("ERROR: ", error);done(error, null);return;

}done(null, result);return;

});}

Node.js

function query(sql, done) {var queryToRun = myQuery.fromString(sql);myBucket.query(queryToRun, function (error, result) {

if (error) {console.log("ERROR: ", error);done(error, null);return;

}done(null, result);return;

});}

Demo Time!

Node.js Application Design

Node.js

Server Backend

Angular

Client Frontend

Node.js Separation of Frontend and Backend

• No Jade markup

• API driven

• Less client and server coupling

• The backend can evolve without affecting the frontend

• Frontend can be extended to web as well as mobile

Multiple Frontends & One Backend

The Node.js Backend

Node.js Configuration

1. // app.js2. var Express = require("express");3. var Couchbase = require("couchbase");4. var BodyParser = require("body-parser");5. var Cors = require("cors");6. var UUID = require("uuid");

7. var app = Express();8. var N1qlQuery = Couchbase.N1qlQuery;

9. app.use(BodyParser.json());10.app.use(BodyParser.urlencoded({ extended: true }));11.app.use(Cors());

12.var cluster = new Couchbase.Cluster("couchbase://localhost");13.cluster.authenticate("demo", "123456");14.var bucket = cluster.openBucket("default");

Node.js Configuration

1. // app.js2. app.get("/", (request, response) => {3. response.send("Hello World!");4. });

5. app.listen(3000, () => {6. console.log("Listening at :3000");7. });

Node.js INSERT Document

1. // app.js2. app.post("/person", (request, response) => {3. if (!request.body.firstname) {4. return response.status(401).send({ code: 401, message: "A `firstname` is required." });5. } else if (!request.body.lastname) {6. return response.status(401).send({ code: 401, message: "A `lastname` is required." });7. }8. request.body.type = "person";9. var statement = "INSERT INTO `" + bucket._name + "` (KEY, VALUE) VALUES ($id, $data)10. RETURNING META().id, `" + bucket._name + "`.*";11. var query = N1qlQuery.fromString(statement);12. bucket.query(query, { "id": UUID.v4(), "data": request.body }, (error, results) => {13. if (error) {14. return response.status(500).send({ code: error.code, message: error.message });15. }16. response.send(results[0]);17. });18.});

Node.js SELECT All Documents

1. // app.js2. app.get("/people", (request, response) => {3. var statement = "SELECT META().id, `" + bucket._name + "`.*4. FROM `" + bucket._name + "` WHERE type = 'person'";5. var query = N1qlQuery.fromString(statement).consistency(N1qlQuery.Consistency.REQUEST_PLUS);6. bucket.query(query, (error, results) => {7. if (error) {8. return response.status(500).send({ code: error.code, message: error.message });9. }10. response.send(results);11. });12.});

Node.js SELECT Single Document

1. // app.js2. app.get("/person/:id", (request, response) => {3. if (!request.params.id) {4. return response.status(401).send({ code: 401, message: "An `id` is required." });5. }6. var statement = "SELECT META().id, `" + bucket._name + "`.*7. FROM `" + bucket._name + "` WHERE type = 'person' AND META().id = $id";8. var query = N1qlQuery.fromString(statement);9. bucket.query(query, { "id": request.params.id }, (error, results) => {10. if (error) {11. return response.status(500).send({ code: error.code, message: error.message });12. }13. response.send(results.length > 0 ? results[0] : {});14. });15.});

Node.js DELETE Document

1. // app.js2. app.delete("/person/:id", (request, response) => {3. var statement = "DELETE FROM `" + bucket._name + "`4. WHERE META().id = $id RETURNING META().id, `" + bucket._name + "`.*";5. var query = N1qlQuery.fromString(statement);6. bucket.query(query, { "id": request.params.id }, (error, results) => {7. if (error) {8. return response.status(500).send({ code: error.code, message: error.message });9. }10. response.send(results);11. });12.});

The Angular Frontend

Angular Component

1. import { Component, OnInit } from '@angular/core';2. import { Http, Headers, RequestOptions } from "@angular/http";3. import "rxjs/Rx";

4. @Component({5. selector: 'app-people',6. templateUrl: './people.component.html',7. styleUrls: ['./people.component.css']8. })9. export class PeopleComponent implements OnInit {

10. public people: Array<any>;11. public input: any;

12. public constructor(private http: Http) { }13. public ngOnInit() { }14. public save() { }

15.}

Get All Documents

1. public constructor(private http: Http) {2. this.people = [];3. this.input = {4. firstname: "",5. lastname: ""6. }7. }

8. public ngOnInit() {9. this.http.get("http://localhost:3000/people")10. .map(results => results.json())11. .subscribe(results => {12. this.people = results;13. });14.}

Create New Document

1. public save() {2. if (this.input.firstname != "" && this.input.lastname != "") {3. let headers = new Headers({ "Content-Type": "application/json" });4. let options = new RequestOptions({ headers: headers });5. this.http.post("http://localhost:3000/person", JSON.stringify(this.input), options)6. .map(results => results.json())7. .subscribe(results => {8. this.people.push(results);9. this.input.firstname = "";10. this.input.lastname = "";11. });12. }13.}

More Complex Node.js Queries

Node.js Travel Sample

1. FlightPath.findAll = function (from, to, callback) {2. var statement = "SELECT faa AS fromAirport, geo " +3. "FROM `" + config.couchbase.bucket + "` r" +4. "WHERE airportname = $1 " +5. "UNION SELECT faa AS toAirport, geo " +6. "FROM `" + config.couchbase.bucket + "` r" +7. "WHERE airportname = $2";8. var query = N1qlQuery.fromString(statement);9. db.query(query, [from, to], function (error, result) {10. if (error) {11. return callback(error, null);12. }13. callback(null, result);14. });15.};

Node.js Travel Sample

1. FlightPath.findAll = function (queryFrom, queryTo, leave, callback) {2. var statement = "SELECT r.id, a.name, s.flight, s.utc, r.sourceairport, r.destinationairport,

r.equipment " +3. "FROM `" + config.couchbase.bucket + "` r" +4. "UNNEST r.schedule s " +5. "JOIN `" + config.couchbase.bucket + "` a ON KEYS r.airlineid " +6. "WHERE r.sourceairport = $1 AND r.destinationairport = $2 AND s.day = $3 ” 7. "ORDER BY a.name";8. var query = N1qlQuery.fromString(statement);9. db.query(query, [queryFrom, queryTo, leave], function (error, result) {10. if (error) {11. return callback(error, null);12. }13. callback(null, result);14. });15.};

Node.js Sample Applications

• https://github.com/couchbaselabs/try-cb-nodejs

• https://github.com/couchbaselabs/restful-angularjs-nodejs

Couchbase N1QL Tutorial

• http://query.pub.couchbase.com/tutorial/

Ottoman ODM

4

3Confidential and Proprietary. Do not distribute without Couchbase consent. © Couchbase 2017. All rights reserved.

Ottoman Model

1. var RecordModel = ottoman.model("Record", {2. firstname: { type: "string" },3. lastname: { type: "string" },4. email: { type: "string" },5. created_at: { type: "Date", default: Date.now }6. });

Ottoman Saving

1. var myRecord = new RecordModel({2. firstname: "Matt",3. lastname: "Groves",4. email: "matthew.groves@couchbase.com"5. });

6. myRecord.save(function (error) {7. if (error) {8. // Error here9. }10. // Success here11.});

Ottoman Finding

1. RecordModel.find({}, function (error, result) {2. if (error) {3. // Error here4. }5. // Array of results here6. });

Where do you find us?

• developer.couchbase.com

• blog.couchbase.com

• @couchbase / @couchbasedev / @mgroves

• forums.couchbase.com

• stackoverflow.com/questions/tagged/couchbase

Frequently Asked Questions

1. How is Couchbase different than Mongo?

2. Is Couchbase the same thing as CouchDb?

3. How did you get to be both incredibly handsome and tremendously intelligent?

4. What is the Couchbase licensing situation?

5. Is Couchbase a Managed Cloud Service?

CouchDB and Couchbase

< Back

memcached

MongoDB vs Couchbase

• Architecture• Memory first architecture• Master-master architecture• Auto-sharding

< Back

• Features• SQL (N1QL)• Full Text Search• Mobile & Sync

Licensing

Couchbase Server Community• Open source (Apache 2)• Binary release is one release behind Enterprise• Free to use in dev/test/qa/prod• Forum support only

Couchbase Server Enterprise• Mostly open source (Apache 2)• Some features not available on Community (XDCR TLS, MDS, Rack Zone, etc)• Free to use in dev/test/qa• Need commercial license for prod• Paid support provided

< Back

Managed Cloud Service (DBaaS)?

Short answer: No.

< Back

Longer answer: Kinda. https://zdatainc.com/couchbase-managed-services/

Longest answer: See me after class.

Recommended