Upgrade to Pro — share decks privately, control downloads, hide ads and more …

ForwardJS - RethinkDB - Getting Started

ForwardJS - RethinkDB - Getting Started

Jorge Silva

July 30, 2015
Tweet

More Decks by Jorge Silva

Other Decks in Programming

Transcript

  1. Schedule 1. What is RethinkDB? 2. RethinkDB query language 3.

    Working with changefeeds 4. Using RethinkDB with Node.js 5. Tutorial: Building a chat app
  2. What is RethinkDB? • Open source database for building realtime

    web applications • NoSQL database that stores schemaless JSON documents • Distributed database that is easy to scale
  3. Built for Realtime Apps • Subscribe to change notifications from

    database queries (changefeeds) • No more polling — the database pushes changes to your app • Reduce the amount of plumbing needed to stream live updates
  4. Built for Realtime Apps • Having your database push changes

    keeps your database as the central source of truth • Having a central source of truth simplifies your architecture
  5. Power and Convenience • Highly expressive query language • Relational

    features like table joins • Powerful admin UI with point- and-click cluster management
  6. RethinkDB Structure Database → Table → Document MySQL: Database →

    Table → Row MongoDB: Database → Collection → Document
  7. Sample Document { "name": "Will Riker", "position": "Commander", "height": 193,

    "birthdate": Mon Aug 19 2335, "ships": [ { "name": "USS Pegasus" }, { "name": "USS Potemkin" }, { "name": "USS Enterprise" }, ], ... }
  8. Differences with Firebase • Firebase is a cloud service, not

    an open-source database • Because Firebase is not a database, it has limited querying abilities • Firebase is made to be queried from the browser
  9. Differences with MongoDB • RethinkDB supports joins and subqueries •

    MongoDB only supports the traditional query-response model. You can't subscribe to queries.
  10. Introduction to ReQL • ReQL embeds natively into your programming

    language • Compose ReQL queries by chaining commands
  11. ReQL Commands • Transformations: map, orderBy, skip, limit, slice •

    Aggregations: group, reduce, count, sum, avg, min, max, distinct, contains • Documents: row, pluck, without, merge, append, difference, keys, hasFields, spliceAt • Writing: insert, update, replace, delete • Control: forEach, range, branch, do, coerceTo, expr
  12. ReQL Commands • Transformations: map, orderBy, skip, limit, slice •

    Aggregations: group, reduce, count, sum, avg, min, max, distinct, contains • Documents: row, pluck, without, merge, append, difference, keys, hasFields, spliceAt • Writing: insert, update, replace, delete • Control: forEach, range, branch, do, coerceTo, expr
  13. ReQL Commands • Transformations: map, orderBy, skip, limit, slice •

    Aggregations: group, reduce, count, sum, avg, min, max, distinct, contains • Documents: row, pluck, without, merge, append, difference, keys, hasFields, spliceAt • Writing: insert, update, replace, delete • Control: forEach, range, branch, do, coerceTo, expr
  14. ReQL Commands • Transformations: map, orderBy, skip, limit, slice •

    Aggregations: group, reduce, count, sum, avg, min, max, distinct, contains • Documents: row, pluck, without, merge, append, difference, keys, hasFields, spliceAt • Writing: insert, update, replace, delete • Control: forEach, range, branch, do, coerceTo, expr
  15. ReQL Commands • Transformations: map, orderBy, skip, limit, slice •

    Aggregations: group, reduce, count, sum, avg, min, max, distinct, contains • Documents: row, pluck, without, merge, append, difference, keys, hasFields, spliceAt • Writing: insert, update, replace, delete • Control: forEach, range, branch, do, coerceTo, expr
  16. Understanding ReQL • All queries are executed by the database,

    not the client • Client driver translates ReQL queries into wire protocol • In JS use e.g. the mul and gt commands instead of the normal operators
  17. Additional ReQL Features • Geospatial indexing for location- based queries

    • Date and time functions • Support for storing binary objects • Execute http requests using r.http
  18. Changefeeds • The changes command returns a cursor that receives

    updates • Each update includes the new and old value of the modified record
  19. Changefeeds r.table("users").changes() r.table("users") .insert({name: "Bob"}) Changefeed output: { new_val: {

    id: '362ae837-2e29-4695-adef-4fa415138f90', name: 'Bob', ... }, old_val: null }
  20. Changefeeds r.table("users").changes() r.table("users") .get("362ae837-2e29-4695-adef-4fa415138f90") .update({name: "Bobbby"}) Changefeed output: { new_val:

    { id: '362ae837-2e29-4695-adef-4fa415138f90', name: 'Bobby' }, old_val: { id: '362ae837-2e29-4695-adef-4fa415138f90', name: 'Bob' } }
  21. Changefeeds r.table("table").get(ID).changes() r.table("table").getAll(ID).changes() r.table("table").between(X, Y).changes() r.table("table").pluck(X, Y, Z).changes() r.table("table").filter(CONDITION).changes() r.table("table").union(ID).changes()

    r.table("table").map(FUNCTION).changes() r.table("table").min(INDEX).changes() r.table("table").max(INDEX).changes() r.table("table").orderBy(INDEX) .limit(N).changes() Commands that currently work with changefeeds:
  22. Client Driver • Use a RethinkDB client driver to access

    the database in your app • Official drivers available for Ruby, Python, and JavaScript • Third-party drivers available for other languages like Go and Clojure
  23. > Client Driver Install the JS client driver from npm

    in your Node.js project: $ npm install rethinkdb --save
  24. Client Driver var r = require("rethinkdb"); r.connect().then(function(conn) { return r.table("users")

    .insert({name: “Bob”}).run(conn) .finally(function () { conn.close(); }); }).then(function(output) { console.log(output); }); Add Bob to the “users” table
  25. Client Driver var r = require("rethinkdb"); r.connect().then(function(conn) { return r.table("users")

    .insert({name: “Bob"}).run(conn) .finally(function () { conn.close(); }); }).then(function(output) { console.log(output); }); Import the RethinkDB module
  26. Client Driver var r = require("rethinkdb"); r.connect().then(function(conn) { return r.table("users")

    .insert({name: “Bob”}).run(conn) .finally(function () { conn.close(); }); }).then(function(output) { console.log(output); }); Connect to the database
  27. Client Driver var r = require("rethinkdb"); r.connect().then(function(conn) { return r.table("users")

    .insert({name: “Bob”}).run(conn) .finally(function () { conn.close(); }); }).then(function(output) { console.log(output); }); ReQL query that inserts a record
  28. Client Driver var r = require("rethinkdb"); r.connect().then(function(conn) { return r.table("users")

    .insert({name: “Bob”}).run(conn) .finally(function () { conn.close(); }); }).then(function(output) { console.log(output); }); Run the query on a connection
  29. Client Driver var r = require("rethinkdb"); r.connect().then(function(conn) { return r.table("users")

    .insert({name: “Bob"}).run(conn) .finally(function () { conn.close(); }); }).then(function(output) { console.log(output); }); Display query response
  30. Client Driver var r = require("rethinkdb"); r.connect().then(function(conn) { return r.table("users")

    .insert({name: “Bob"}).run(conn) .finally(function () { conn.close(); }); }).then(function(output) { console.log(output); }).error(function(err) { console.log("Failed:", err); }); Handle errors emitted by Promise
  31. Using Changefeeds r.connect().then(function(conn) { return r.table("fellowship") .changes().run(conn); }) .then(function(cursor) {

    cursor.each(function(err, item) { console.log(item); }); }); Display every change on the “fellowship” table
  32. Using Changefeeds Attach a changefeed to the table r.connect().then(function(conn) {

    return r.table("fellowship") .changes().run(conn); }) .then(function(cursor) { cursor.each(function(err, item) { console.log(item); }); });
  33. Using Changefeeds Iterate over every value passed into the cursor

    r.connect().then(function(conn) { return r.table("fellowship") .changes().run(conn); }) .then(function(cursor) { cursor.each(function(err, item) { console.log(item); }); });
  34. Using Changefeeds r.connect().then(function(conn) { return r.table("fellowship") .changes().run(conn); }) .then(function(cursor) {

    cursor.each(function(err, item) { console.log(item); }); }); Display received changes in the console
  35. Using Socket.io • Powerful framework for realtime client/server communication •

    Supports WebSockets, long polling, and other transports • Lets you send JSON messages between your app and frontend
  36. Socket.io (Server) var sockio = require("socket.io"); var app = require("express")();

    var r = require("rethinkdb"); var io = sockio.listen(app.listen(8090)); r.connect().then(function(conn) { return r.table("players") .orderBy({index: r.desc("score")}) .limit(5).changes().run(conn); }) .then(function(cursor) { cursor.each(function(err, data) { io.sockets.emit("update", data); }); }); Broadcast score changes over Socket.io
  37. Socket.io (Server) var sockio = require("socket.io"); var app = require("express")();

    var r = require("rethinkdb"); var io = sockio.listen(app.listen(8090)); r.connect().then(function(conn) { return r.table("players") .orderBy({index: r.desc("score")}) .limit(5).changes().run(conn); }) .then(function(cursor) { cursor.each(function(err, data) { io.sockets.emit("update", data); }); }); Load the Socket.io module
  38. Socket.io (Server) var sockio = require("socket.io"); var app = require("express")();

    var r = require("rethinkdb"); var io = sockio.listen(app.listen(8090)); r.connect().then(function(conn) { return r.table("players") .orderBy({index: r.desc("score")}) .limit(5).changes().run(conn); }) .then(function(cursor) { cursor.each(function(err, data) { io.sockets.emit("update", data); }); }); Instantiate Socket.io server
  39. Socket.io (Server) var sockio = require("socket.io"); var app = require("express")();

    var r = require("rethinkdb"); var io = sockio.listen(app.listen(8090)); r.connect().then(function(conn) { return r.table("players") .orderBy({index: r.desc("score")}) .limit(5).changes().run(conn); }) .then(function(cursor) { cursor.each(function(err, data) { io.sockets.emit("update", data); }); }); Attach a changefeed to the query
  40. Socket.io (Server) var sockio = require("socket.io"); var app = require("express")();

    var r = require("rethinkdb"); var io = sockio.listen(app.listen(8090)); r.connect().then(function(conn) { return r.table("players") .orderBy({index: r.desc("score")}) .limit(5).changes().run(conn); }) .then(function(cursor) { cursor.each(function(err, data) { io.sockets.emit("update", data); }); }); Broadcast updates to all Socket.io connections
  41. Socket.io (Client) <html> <head> <title>Real-time web app</title> <script src="/socket.io/socket.io.js"></script> <script>

    var socket = io.connect(); socket.on("update", function(data) { console.log("Update:", data); }); Receive Socket.io updates on frontend
  42. Socket.io (Client) <html> <head> <title>Real-time web app</title> <script src="/socket.io/socket.io.js"></script> <script>

    var socket = io.connect(); socket.on("update", function(data) { console.log("Update:", data); }); Load the Socket.io client script
  43. Socket.io (Client) <html> <head> <title>Real-time web app</title> <script src="/socket.io/socket.io.js"></script> <script>

    var socket = io.connect(); socket.on("update", function(data) { console.log("Update:", data); }); Connect to the Socket.io server
  44. Socket.io (Client) <html> <head> <title>Real-time web app</title> <script src="/socket.io/socket.io.js"></script> <script>

    var socket = io.connect(); socket.on("update", function(data) { console.log("Update:", data); }); Create handler for “update” messages
  45. Socket.io (Client) <html> <head> <title>Real-time web app</title> <script src="/socket.io/socket.io.js"></script> <script>

    var socket = io.connect(); socket.on("update", function(data) { console.log("Update:", data); }); Display update in browser console
  46. #1: Clone the repository Clone From GitHub: git clone https://github.com/thejsj/

    rethinkdb-workshop.git Download Tarball: https://github.com/thejsj/rethinkdb- workshop/tarball/master
  47. #2: Install Dependencies // Go to the project directory cd

    rethinkdb-workshop // Install dependencies npm install
  48. #3: Go to config/default.js Update your RethinkDB database configuration var

    config = { "rethinkdb": { "host": "localhost", // or rethinkdb.thejsj.com "port": 28015, "db" : "rethinkdb_workshop" // or GITHUB_HANDLE_rethinkdb_workshop },
  49. #4: Go to server/index.js Look for the comments in order

    to write the correct ReQL queries // Step 1 // Write a query
  50. #5: Switch database Connect to the following database, so we

    can all share messages var config = { "rethinkdb": { "host": "rethinkdb.thejsj.com", "port": 29015, "db" : "GITHUB_HANDLE_rethinkdb_workshop" },
  51. Next steps • Advanced Commands: `r.do`, `r.branch`, `r.forEach` • Map/Reduce

    queries • Indexes (multi, compound, index functions, geospatial) • Sharding and replication