nosql and javascript: a love story

41
NoSQL & JavaScript a Love Story! by Alexandre Morgaut TakeOff Conf - Lille 2013

Upload: alexandre-morgaut

Post on 29-Aug-2014

2.720 views

Category:

Technology


3 download

DESCRIPTION

You may all know that JSON is a subset of JavaScript, but... Did you know that HTML5 implements NoSQL databases? Did you know that JavaScript was recommended for REST by Roy T. Fielding himself? Did you know that map & reduce are part of the native JavaScript API? Did you know that most NoSQL solutions integrate a JavaScript engine? CouchDB, MongoDB, WakandaDB, ArangoDB, OrientDB, Riak.... And when they don't, they have a shell client which does... The story of NoSQL and JavaScript goes beyond your expectations and open more opportunities than you might imagine... What better match could you find than a flexible and dynamic language for schemaless databases? Isn't, an event-driven language what you were waiting for to manage eventually consistency? When NoSQL doesn't come to JavaScript, JavaScript comes to NoSQL, and does it very well...

TRANSCRIPT

NoSQL & JavaScripta Love Story!

by Alexandre Morgaut

TakeOff Conf - Lille 2013

PresentationW3C AC member

Wakanda Community

Web Architect

JS Expert

REST Lover

NoSQL Fanboy@amorgaut

NoSQL facts

NoSQL FactsMostly Schemaless

Often with REST / JSON API

Many store JSON

Many embed a JavaScript engine

Map / Reduce

events

Many propose a JavaScript Shell

NoSQL FamiliesDocument Store

Key-value store

Graph

Object store

Column store

NoSQL FamiliesDocument Store

Key-value store

Graph

Object store

Column store

NoSQL FamiliesDocument Store

Key-value store

Graph

Object store

Column store

JavaScript facts

JavaScript FactsCreated in 1995

Running in Netscape Server in 1996, and then in IIS

Mostly Event-Driven

Recommended in the REST definition in 2000

Integrated in CouchDB in 2007

HTML5 Datastores appeared in 2009

SpiderMonkey3 JIT Compilers: TraceMonkey, JägerMonkey, IonMonkey

V8JIT Compiler : CrankShaft

webkit JavaScriptCore: JSCSquirrelFish Extreme: SFX aka Nitro

(JIT Compiler inside)

Trident: MSHTMLChakra

-> Classic JScript, Managed JScript, & JScript.NET

TamarinJIT Compiler : NanoJIT

-> ActionScript / “ECMAScript 4”

CarakanPreviously: Linear A, Linear B, Futhark

RhinoInterpreted or Compiled execution

CC++

C++Java

?

?C++

Nashorn?

JavaScript Engines

SpiderMonkey

V8

JavaScriptCore

Rhino

Trident / Chakra

Server-Side JavaScript

JavaScript & Databases

JavaScript & Databases

Netscape Enterprise Server

Microsoft: JScript, JScript.NET, ActiveX

Mozilla Rhino

JSDB

APE Project

W3C Web SQL

Netscape Enterprise Server

SQLTable()

DbPool

start/home.html

Shared Connections

pool = new DbPool("ORACLE", addr, user, pwd, "", 5, true);connection = pool.connection("A connection");

cursor = connection.cursor("select name from customer");

if ( cursor && (connection.majorErrorCode() == 0) ) { // Get the first row cursor.next(); // Display the values write("<B>Customer Name:</B> " + cursor.name + "<BR>"); //Close the cursor cursor.close();}

Note: Netscape Enterprise Server merged with Javagator to become iPlanet

MS JScript on the server

Active Server Page

runat=”server”

Windows Script Hosting

.NET

conn = Server.CreateObject("ADODB.Connection");

conn.Open(dsn, login, password);

reccordset = conn.Execute(sqlQuery);result = [];

while (!reccordset.EOF) {

result.push({ field1: reccordset("field1"), field2: reccordset("field2") }); rsAuthor2.MoveNext; }

conn.Close();conn = null;

Note: JScript is running on Microsoft IIS since 1997

MS JScript in the Browser

ActiveXObject

only IE

var connection = new ActiveXObject("ADODB.Connection");  connection.Open(dsn, login, password);var reccordset = new ActiveXObject("ADODB.Recordset"); reccordset.Open(sqlQuery, connection);reccordset.MoveFirst;

while(!reccordset.eof) { document.write(reccordset.fields(1)); reccordset.movenext;} reccordset.close;connection.close;

Mozilla Rhino

Java environment

Access to JDBC

ex: RingoJS

importPackage(java.sql);java.lang.Class.forName("org.sqlite.JDBC");

conn = DriverManager.getConnection("jdbc:sqlite:test.db");stat = conn.createStatement();resultSet = stat.executeQuery("select * from people;");

while (resultSet.next()){ print( resultSet.getString("name") + " - " + resultSet.getString("occupation") );}

resultSet.close();stat.close();conn.close();

https://developer.mozilla.org/en-US/docs/Rhino

JSDB

SpiderMonkey

Shell

JS Server

var db = new ODBC(dsn);var result = db.query("select * from mytable");

var searcher = new Index;for (var i=1; i <= result.count; i++){ searcher.add(result.get('NAME'));}

var i = searcher.find('Mr. Smith');var r = result.getRow(i + 1);

writeln('Data for Mr. Smith');writeln(r.toString());

db.close();

http://www.jsdb.org/

APE Project

Real Time Web

Comet

Web Sockets

MySQL

var sql = new Ape.MySQL(ip + ":3306", user, password, db);

Ape.registerCmd('foo', true, function(params, cmd) {

cmd.user.sendRaw( 'bar', { hello: 'world', echo: params.ping } ); sql.query( 'INSERT INTO table(log) VALUES("' + Ape.MySQL.escape(params.ping) + '")', function(res, errorNo) { Ape.log('Inserted ' + this.getInsertId()); } );});

http://www.ape-project.org/

Note: APE means “Ajax Push Engine”

W3C Web SQL

HTML5

Safari

Chrome

Opera

Sync / Async

db.transaction(function (tx) { tx.executeSql('CREATE TABLE IF NOT EXISTS foo (id unique, text)'); tx.executeSql('INSERT INTO foo (id, text) VALUES (1, "synergies")');});

http://html5doctor.com/introducing-web-sql-databases/

Note: standard paused because current implementations are only based on SQLite

var db = openDatabase('mydb', '1.0', 'my first db', 2 * 1024 * 1024);

result = x.executeSqlSync('SELECT * FROM foo');for (var i = 0, len = results.rows.length; i < len; i++) { alert(results.rows.item(i).text);}

tx.executeSql('SELECT * FROM foo', [], function (tx, results) { for (var i = 0, len = results.rows.length; i < len; i++) { alert(results.rows.item(i).text); }});

Data as a Service (DaaS)

Data as a Service

APPOData

GData

Amazon APIs

Twitter APIs

Touching the DB heart

Key-Value: Web Storage, Riak

Document: CouchDB, MongoDB, IndexedDB

Object: JavaScriptDB, WakandaDB

Multi-Model: OrientDB & ArangoDB

Touching the DB Heart

Key - Value

Web Storage

W3C / WHATWG

HTML5

local

session

events

// set or get items by methodslocalStorage.setItem("storedItem", "value");var value = localStorage.getItem("storedItem");

http://www.w3.org/TR/webstorage/

// sync interface when data change, even from other windowwindow.addEventListener("storage", handle_storage, false);

// set or get items using the store as a maplocalStorage.storedItem = value;var value = localStorage.storedItem;

// accessible only for this sessionvar foo = sessionStorage.bar;sessionStorage.bar = foo;

Note: Firefox used to propose “globalStorage”, Wakanda implements “user.storage”

RiakBuckets

REST / JSON

Map / Reduce

Erlang alternative:

SpiderMonkey

// Map: compute the daily variance, key it by the monthfunction(value, keyData, arg){ var data = Riak.mapValuesJson(value)[0]; var month = value.key.split('-').slice(0,2).join('-'); var obj = {}; obj[month] = data.High - data.Low; return [ obj ];}

// Reduce: find the maximum variance per monthfunction(values, arg) { return [values.reduce(function(acc, item){ for (var month in item) { acc[month] = acc[month] ? Math.max(item[month], acc[month]) : item[month]; } return acc; })];}

{"inputs": "goog", "query": [ {"map": {"language": "javascript", "source": "function(value, keyData, arg){...}" }}, {"reduce": {"language": "javascript", "source": "function(values, arg){...}", "keep": true }} ]}

Document

IndexedDBW3C / WHATWG

HTML5

Sync / Async

Indexes

Transactions

Cursors

request.onerror = function(event) { // Do something with request.errorCode!};request.onsuccess = function(event) { // Do something with request.result!};

http://www.w3.org/TR/IndexedDB/

var request = indexedDB.open("MyTestDatabase", 3);

request.onupgradeneeded = function(event) { // Update object stores and indices .... }

var objectStore = db.createObjectStore("customers", { keyPath: "ssn" });

objectStore.createIndex("name", "name", { unique: false });objectStore.add({ ssn: "444-44-4444", name: "Bill", age: 35});

var transaction = db.transaction(["customers"], IDBTransaction.READ_WRITE);

CouchDB

Views

JSON*

Map / Reduce

Erlang alternative:

Spidermonkey

function(doc) { if (doc.Type == "customer") { emit(doc.LastName, {FirstName: doc.FirstName, Addr: doc.Address}); emit(doc.FirstName, {LastName: doc.LastName, Addr: doc.Address}); }}

{ "total_rows":2, "offset":0, "rows": [ { "id":"64ACF01B05F53ACFEC48C062A5D01D89", "key":"Katz", "value":{"FirstName":"Damien", "Addr":"Charlotte NC"} }, { "id":"64ACF01B05F53ACFEC48C062A5D01D89", "key":"Damien", "value":{"LastName":"Katz", "Addr":"Charlotte NC"} }, ]}

http://wiki.apache.org/couchdb/HTTP_view_API

Note: CouchDB moved from XML to JSON & JS in 2007** http://jan.prima.de/~jan/plok/archives/89-CouchDb-updates.html

CouchBase

CouchDB alternative

using V8

adding memcache

meant to be more scalable

http://www.couchbase.com/

MongoDBSpidermonkey

BSON

Map / Reduce

REST / JSON

REST / JS

Shell

var map = function() { emit(this.author, {votes: this.votes});};

http://www.mongodb.org/display/DOCS/MapReduce

{ text: "lmao! great article!", author: 'kbanker', votes: 2}

// Add up all the votes for each key.var reduce = function(key, values) { var sum = 0; values.forEach(function(doc) { sum += doc.votes; }); return {votes: sum};};

var op = db.comments.mapReduce(map, reduce, {out: "mr_results"});

Object

Persevere JavaScriptDB

Rhino

REST / JSON

JSON Schema

JSON Path

JSON Query

{"id":"generated.js","sources":[ { "name":"Data", "extends":"Object", "schema":{ "extends":{"$ref":"../Class/Object"}, hello : function() { console.log("hello hi"); }, "prototype":{ } } }]}

curl localhost:8080/Data/1

({"id":"1","test":12345})

Data.hello(); // INFO: hi there

var d = new Data();d.test = 12345;

http://www.sitepen.com/blog/2009/04/20/javascriptdb-perseveres-new-high-performance-storage-engine/

WakandaDBWebkit JavaScriptCore

REST / JSON

Data Classes

auto-updatable

accessors

events

methods

john = ds.Person.find("fistName eq John");

conferences = john.allConferences;

JohnJSConferences = conferences.filter("title eq :1", "*JavaScript*");

JSAttendeesJohnMet = JSConferences.allPeople;

http://wakanda.org/

Multi-Model

ArangoDB

V8

events

filters

transactions

Shell

actions.defineHttp({ url : "world", context : "api", callback : function (req, res) { var collection = db._collection(req.parameter.collection); if (collection == null) { ... } else { ... } actions.resultOk(req, res, actions.HTTP_OK, result); }});

http://www.ape-project.org/

OrientDB

rhino

REST / JSON

transactions

hooks (events)

stored procedures

// create function getAllCustomerreturn db.query("select from V")

http://www.orientdb.org/

db.begin();try {" // some code" db.commit()} catch (e) {" db.rollback();"}

new com.orientechnologies.orient.core.record.impl.ODocument('Profile').field('name', 'Luca').save()

Reaching the DB

mongoose

mongodb-rhino

riak control

backbone-couchdb

dojox.data.couchDBRestStore

node-cassandra

WAF (Wakanda)

Ext.data.proxy.Wakanda

arango.client

voltdb-client-nodejs

redis-node-client

orientdb-api.js

Reaching the DB