full stack development with node and nosql - austin node.js group - october 2016

65
Full Stack Development with Node.js and NoSQL Matthew Groves (@mgroves) #couchbase

Upload: matthew-groves

Post on 16-Apr-2017

122 views

Category:

Software


2 download

TRANSCRIPT

Full Stack Development with Node.js and NoSQL

Matthew Groves (@mgroves)

#couchbase

©2016 Couchbase Inc. 2

Where am I?

• Austin Node.JS User Group

• http://www.meetup.com/noders/

©2016 Couchbase Inc. 3

Who am I?

• Matthew D. Groves

• Developer Advocate for Couchbase

• @mgroves on Twitter

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

• “I am not an expert, but I am an enthusiast.” – Alan Stevens

©2016 Couchbase Inc. 4

Couchbase and CouchDB

Couchbase is to CouchDBas

MySQL is to SQL Server

©2016 Couchbase Inc. 5

Tweet something, get a sticker!

Use #Couchbase

Tweet something interesting you’ve learned.Tweet a picture.I’ve got stickers!

Full Stack Development with Node.js and NoSQL

Matthew Groves (@mgroves)

#couchbase

The Part of the Stack With Software Application Development and

Infrastructure Management with Node.js and Second Generation Non-Relational Document Databases Which by the Way

Actually Do Have a SQL-like Query Language

©2016 Couchbase Inc. 8

Full Stack Developer

©2016 Couchbase Inc. 9

Application Stacks

©2016 Couchbase Inc. 10

NoSQL: Flexible JSON Schema

©2016 Couchbase Inc. 11

Where is NoSQL a Good Fit?

Low-latency Critical

High Throughput or Large Numbers of Users

Unknown Demand with Sudden growth

Predominantly Direct Document Access

Read / Mixed / Write-heavy Workloads

Traditional Business Applications

Transaction-heavy Apps

Legacy Hardware

Full ACID support

Web / Mobile / IoT Legacy Business Apps

©2016 Couchbase Inc. 12

Where is NoSQL a Good Fit?

http://info.couchbase.com/15Q1TopTenUC.html

©2016 Couchbase Inc. 13

What is Couchbase?

Couchbase is a distributed operational database that enables you to develop with agility and operate at any scale.

Managed Cache Key-Value Store Document Database Embedded Database Sync Management

©2016 Couchbase Inc. 14

Agility

Easier, Faster Development Flexible Data Modeling Powerful Querying

SQL Integration & Migration Big Data Integration Mobile / IoT

©2016 Couchbase Inc. 15

Scale

Elastic Scalability Consistent High Performance Always-on Availability

Multi-Data Center Deployment Simple, Powerful Administration Enterprise Grade Security

©2016 Couchbase Inc. 16

Couchbase Developer

©2016 Couchbase Inc. 17

Couchbase and Big Data

©2016 Couchbase Inc. 18

Couchbase Server – Single Node Architecture

©2016 Couchbase Inc. 19

Simplified Administration: Console

©2016 Couchbase Inc. 20

Simplified Administration: RESTful API

©2016 Couchbase Inc. 21

Accessing Data: Key access using Document ID

©2016 Couchbase Inc. 22

Accessing Data: Views using static queries

©2016 Couchbase Inc. 23

Accessing Data: Queries using N1QL

©2016 Couchbase Inc. 24

The Couchbase Node.js SDK

Uses the Couchbase C library

Compatible with Node.js frameworks

Available on NPM

©2016 Couchbase Inc. 25

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", "password");

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

//creating and saving a Documentvar document = {

firstname: "Matt",lastname: "Groves"

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

©2016 Couchbase Inc. 26

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;

});}

©2016 Couchbase Inc. 27

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;

});}

©2016 Couchbase Inc. 28

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;

});}

©2016 Couchbase Inc. 29

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;

});}

©2016 Couchbase Inc. 30

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;

});}

©2016 Couchbase Inc. 31

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 (web)

©2016 Couchbase Inc. 33

The CEAN Stack

©2016 Couchbase Inc. 34

Stack Design

AngularJS

Client Frontend

Node.js/Express

Server Backend

©2016 Couchbase Inc. 35

Multiple Frontends & One Backend

©2015 Couchbase Inc. 36

The Angular 2 Frontend

©2016 Couchbase Inc. 37

Get all documents

// list.component.ts

export class ListComponent implements OnInit {

public people: Array<any>;

public constructor(private http: Http) { this.people = []; }

public ngOnInit() {this.http.get("http://localhost:3000/api/getAll")

.map(result => result.json())

.subscribe(results => {this.people = results;

}, error => {console.error(error);

});}

}

©2016 Couchbase Inc. 38

Get all documents

<!-- list.component.html -->

<tbody><tr *ngFor="let person of people">

<td>{{person.firstname}}</td><td>{{person.lastname}}</td><td>{{person.email}}</td><td>

<a [routerLink]="['/item', person.id]">edit</a>|<a href="#" (click)="delete(person.id)">delete</a>

</td></tr>

</tbody>

©2016 Couchbase Inc. 39

Save a document

<!-- item.component.html -->

<form><div class="form-group">

<label for="firstname">First Name</label><input type="text" class="form-control" id="firstname" placeholder="First Name" [(ngModel)]="person.firstname">

</div><div class="form-group">

<label for="lastname">Last Name</label><input type="text" class="form-control" id="lastname" placeholder="Last Name" [(ngModel)]="person.lastname">

</div><div class="form-group">

<label for="email">Email</label><input type="text" class="form-control" id="email" placeholder="Email" [(ngModel)]="person.email">

</div><button type="button" class="btn btn-danger" [routerLink]="['/']">Cancel</button><button type="button" class="btn btn-success" (click)="save()">Save</button>

</form>

©2016 Couchbase Inc. 40

Save a document

// item.component.ts

export class ItemComponent implements OnInit {

public person: any;

public save() {let headers = new Headers({ 'Content-Type': 'application/json' });let options = new RequestOptions({ headers: headers });this.http.post("http://localhost:3000/api/save", JSON.stringify(this.person), options)

.map(result => result.json())

.subscribe(results => {this.location.back();

}, error => {console.error(error);

});}

}

©2015 Couchbase Inc. 41

The Node.js Backend

©2016 Couchbase Inc. 42

Node.js Configuration

// config.json

{"couchbase": {

"server": "localhost:8091","bucket": "default"

}}

©2016 Couchbase Inc. 43

Node.js Configuration

// app.js file

var express = require("express");var bodyParser = require("body-parser");var couchbase = require("couchbase");var path = require("path");var config = require("./config");var app = express();

©2016 Couchbase Inc. 44

Node.js Configuration

// app.js continued...

app.use(bodyParser.json());app.use(bodyParser.urlencoded({ extended: true }));

module.exports.bucket =(new couchbase.Cluster(config.couchbase.server)).openBucket(config.couchbase.bucket);

app.use(express.static(path.join(__dirname, "public")));

var routes = require("./routes/routes.js")(app);

var server = app.listen(3000, function () {console.log("Listening on port %s...", server.address().port);

});

©2016 Couchbase Inc. 45

Node.js Create or Update Endpoint

// routes.js

app.post("/api/create", function(req, res) {if(!req.body.firstname) {

return res.status(400).send({"status": "error", "message": ”First Name?"});}// …RecordModel.save(req.body, function(error, result) {

if(error) {return res.status(400).send(error);

}res.send(result);

});});

©2016 Couchbase Inc. 46

Node.js Get Document Endpoint

// routes.js continued...

app.get("/api/get", function(req, res) {if(!req.query.document_id) {

return res.status(400).send({"status": "error", "message": ”Document ID?"});}RecordModel.getByDocumentId(req.query.document_id, function(error, result) {

if(error) {return res.status(400).send(error);

}res.send(result);

});});

©2016 Couchbase Inc. 47

Node.js Delete Endpoint

// routes.js continued...

app.post("/api/delete", function(req, res) {if(!req.body.document_id) {

return res.status(400).send({"status": "error", "message": ”ID?"});}RecordModel.delete(req.body.document_id, function(error, result) {

if(error) {return res.status(400).send(error);

}res.send(result);

});});

©2016 Couchbase Inc. 48

Node.js Upsert Document Function

// recordmodel.js

RecordModel.save = function(data, callback) {var jsonObject = {

type: "user",firstname: data.firstname,lastname: data.lastname,email: data.email

}var documentId = data.document_id ? data.document_id : uuid.v4();db.upsert(documentId, jsonObject, function(error, result) {

if(error) {return callback(error, null);

}callback(null, {message: "success", data: result});

});}

©2016 Couchbase Inc. 49

Couchbase JSON Document

©2016 Couchbase Inc. 50

Node.js Get Document with N1QL Function

// recordmodel.js continued…

RecordModel.getByDocumentId = function(documentId, callback) {var statement = "SELECT firstname, lastname, email " +

"FROM `" + config.couchbase.bucket + "` AS users " +"WHERE META(users).id = $1";

var query = N1qlQuery.fromString(statement);db.query(query, [documentId], function(error, result) {

if(error) {return callback(error, null);

}callback(null, result);

});};

©2016 Couchbase Inc. 51

Node.js Delete Document Function

// recordmodel.js continued...

RecordModel.delete = function(documentId, callback) {db.remove(documentId, function(error, result) {

if(error) {callback(error, null);return;

}callback(null, {message: "success", data: result});

});};

©2015 Couchbase Inc. 52

More Complex Node.js Queries

©2016 Couchbase Inc. 53

Node.js Travel Sample

FlightPath.findAll = function(from, to, callback) {var statement = "SELECT faa AS fromAirport, geo " +

"FROM `" + config.couchbase.bucket + "` r" +"WHERE airportname = $1 " +"UNION SELECT faa AS toAirport, geo " +"FROM `" + config.couchbase.bucket + "` r" +"WHERE airportname = $2";

var query = N1qlQuery.fromString(statement);db.query(query, [from, to], function(error, result) {

if(error) {return callback(error, null);

}callback(null, result);

});};

©2016 Couchbase Inc. 54

Node.js Travel Sample

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

" r.sourceairport, r.destinationairport, r.equipment " +"FROM `" + config.couchbase.bucket + "` r" +"UNNEST r.schedule s " +"JOIN `" + config.couchbase.bucket + "` a ON KEYS r.airlineid " +"WHERE r.sourceairport = $1 AND r.destinationairport = $2 AND s.day = $3 ”"ORDER BY a.name";

var query = N1qlQuery.fromString(statement);db.query(query, [queryFrom, queryTo, leave], function(error, result) {

if(error) {return callback(error, null);

}callback(null, result);

});};

©2016 Couchbase Inc. 55

Node.js Sample Applications

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

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

©2016 Couchbase Inc. 56

Couchbase N1QL Tutorial

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

©2015 Couchbase Inc. 57

Ottoman ODMhttps://www.npmjs.com/package/ottoman

©2016 Couchbase Inc. 58

Ottoman Model

var RecordModel = ottoman.model("Record", {firstname: {type: "string”},lastname: {type: "string"},email: {type: "string"},created_at: {type: “Date”, default: Date.now}

});

©2016 Couchbase Inc. 59

Ottoman Saving

var myRecord = new RecordModel({firstname: "Matt",lastname: "Groves",email: "[email protected]"

});

myRecord.save(function(error) {if(error) {

// Error here}// Success here

});

©2016 Couchbase Inc. 60

Ottoman Finding

RecordModel.find({}, function(error, result) {if(error) {

// Error here}// Array of results here

});

©2015 Couchbase Inc. 61

Couchbase Mobile

©2016 Couchbase Inc. 62

Couchbase LiteEmbedded NoSQL Database

Sync GatewaySecure Synchronization

Couchbase

ServerCloud NoSQL Database

Couchbase Mobile

©2016 Couchbase Inc. 63

NativeScript Demo

https://github.com/couchbaselabs/nativescript-couchbase

©2016 Couchbase Inc. 64

Couchbase, everybody!

http://couchbase.com/connect

http://info.couchbase.com/Connect16_Livestream_Registration.html

©2016 Couchbase Inc. 65

Where do you find us?

• developer.couchbase.com

• blog.couchbase.com

• forums.couchbase.com

• @couchbasedev

• #couchbase

• @mgroves

• @couchbase