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...
4. NoSQL Facts
Mostly Schemaless
Often with REST / JSON API
Many store JSON
Many embed a JavaScript engine
Map / Reduce
events
Many propose a JavaScript Shell
9. JavaScript Facts
Created 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
10. JavaScript Engines
C+
C +
SpiderMonkey webkit JavaScriptCore: JSC
3 JIT Compilers: SquirrelFish Extreme: SFX aka Nitro
TraceMonkey, (JIT Compiler inside)
JägerMonkey,
IonMonkey
Jav C+
a +
Rhino V8
Interpreted or Compiled execution JIT Compiler: CrankShaft
Nashorn?
?
Trident: MSHTML
Chakra
-> Classic JScript, Managed JScript, & JScript.NET
C+ ?
+
Tamarin Carakan
JIT Compiler: NanoJIT
-> ActionScript / “ECMAScript 4”
Previously: Linear A, Linear B, Futhark
13. JavaScript & Databases
Netscape Enterprise Server
Microsoft: JScript, JScript.NET, ActiveX
Mozilla Rhino
JSDB
APE Project
W3C Web SQL
14. Netscape Enterprise Server
SQLTable() pool = new DbPool("ORACLE", addr, user, pwd, "", 5, true);
connection = pool.connection("A connection");
cursor = connection.cursor("select name from customer");
DbPool if ( cursor && (connection.majorErrorCode() == 0) ) {
// Get the first row
cursor.next();
// Display the values
write("<B>Customer Name:</B> " + cursor.name + "<BR>");
start/home.html }
//Close the cursor
cursor.close();
Shared Connections
Note: Netscape Enterprise Server merged with Javagator to become iPlanet
15. MS JScript on the server
conn = Server.CreateObject("ADODB.Connection");
Active Server Page conn.Open(dsn, login, password);
reccordset = conn.Execute(sqlQuery);
result = [];
runat=”server” while (!reccordset.EOF) {
result.push({
field1: reccordset("field1"),
field2: reccordset("field2")
Windows Script Hosting });
rsAuthor2.MoveNext;
}
.NET
conn.Close();
conn = null;
Note: JScript is running on Microsoft IIS since 1997
16. MS JScript in the Browser
var connection = new ActiveXObject("ADODB.Connection");
connection.Open(dsn, login, password);
var reccordset = new ActiveXObject("ADODB.Recordset");
ActiveXObject
reccordset.Open(sqlQuery, connection);
reccordset.MoveFirst;
while(!reccordset.eof) {
only IE }
document.write(reccordset.fields(1));
reccordset.movenext;
reccordset.close;
connection.close;
17. Mozilla Rhino
importPackage(java.sql);
java.lang.Class.forName("org.sqlite.JDBC");
Java environment conn = DriverManager.getConnection("jdbc:sqlite:test.db");
stat = conn.createStatement();
resultSet = stat.executeQuery("select * from people;");
while (resultSet.next()){
Access to JDBC print(
resultSet.getString("name") +
" - " +
resultSet.getString("occupation")
);
ex: RingoJS
}
resultSet.close();
stat.close();
conn.close();
https://developer.mozilla.org/en-US/docs/Rhino
18. JSDB
var db = new ODBC(dsn);
var result = db.query("select * from mytable");
SpiderMonkey
var searcher = new Index;
for (var i=1; i <= result.count; i++)
{
searcher.add(result.get('NAME'));
}
Shell var i = searcher.find('Mr. Smith');
var r = result.getRow(i + 1);
writeln('Data for Mr. Smith');
writeln(r.toString());
JS Server db.close();
http://www.jsdb.org/
19. APE Project
var sql = new Ape.MySQL(ip + ":3306", user, password, db);
Ape.registerCmd('foo', true, function(params, cmd) {
Real Time Web cmd.user.sendRaw(
'bar', {
hello: 'world',
echo: params.ping
Comet
}
);
sql.query(
'INSERT INTO table(log) VALUES("' +
Web Sockets
Ape.MySQL.escape(params.ping) +
'")',
function(res, errorNo) {
Ape.log('Inserted ' + this.getInsertId());
}
MySQL
);
});
Note: APE means “Ajax Push Engine”
http://www.ape-project.org/
20. W3C Web SQL
HTML5 var db = openDatabase('mydb', '1.0', 'my first db', 2 * 1024 * 1024);
db.transaction(function (tx) {
Safari tx.executeSql('CREATE TABLE IF NOT EXISTS foo (id unique, text)');
tx.executeSql('INSERT INTO foo (id, text) VALUES (1, "synergies")');
});
Chrome 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);
}
});
Opera result = x.executeSqlSync('SELECT * FROM foo');
for (var i = 0, len = results.rows.length; i < len; i++) {
alert(results.rows.item(i).text);
Sync / Async }
Note: standard paused because current implementations are only based on SQLite
http://html5doctor.com/introducing-web-sql-databases/
26. Web Storage
W3C / WHATWG // set or get items by methods
localStorage.setItem("storedItem", "value");
var value = localStorage.getItem("storedItem");
HTML5 // set or get items using the store as a map
localStorage.storedItem = value;
var value = localStorage.storedItem;
local // accessible only for this session
var foo = sessionStorage.bar;
sessionStorage.bar = foo;
session // sync interface when data change, even from other window
window.addEventListener("storage", handle_storage, false);
events
Note: Firefox used to propose “globalStorage”, Wakanda implements “user.storage”
http://www.w3.org/TR/webstorage/
27. Riak
Buckets
{"inputs": "goog",
"query": [
{"map": {"language": "javascript",
"source": "function(value, keyData, arg){...}"
}},
REST / JSON
{"reduce": {"language": "javascript",
"source": "function(values, arg){...}",
"keep": true
}}
]
}
Map / Reduce
// Map: compute the daily variance, key it by the month
function(value, keyData, arg){
Erlang alternative: 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 ];
SpiderMonkey
}
// Reduce: find the maximum variance per month
function(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;
})];
}