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

Introduction to RethinkDB : DevMountain

Introduction to RethinkDB : DevMountain

Workshop given at Dev Mountain on May 6th, 2015.

Avatar for Jorge Silva

Jorge Silva

May 09, 2015
Tweet

More Decks by Jorge Silva

Other Decks in Programming

Transcript

  1. 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
  2. Built for Realtime Apps • Subscribe to change notifications from

    database queries • No more polling — the database pushes changes to your app • Reduce the amount of plumbing needed to stream live updates
  3. RethinkDB Structure Database → Table → Document MySQL: Database →

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

    "birthdate": Mon Aug 19 2335, "ships": [ { "name": "USS Pegasus" }, { "name": "USS Potemkin" }, { "name": "USS Enterprise" }, ], ... }
  5. Introduction to ReQL • ReQL embeds natively into your programming

    language • Compose ReQL queries by chaining commands
  6. 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
  7. Secondary Indexes • Queries performed against indexes are much faster

    • Can index on a single property, multiple fields, or arbitrary ReQL expressions
  8. Anonymous Functions r.range(5).map(function(i) { return i.mul(2); }) Multiply each value

    by 2 You can pass anonymous functions to commands like map and reduce:
  9. The r.row command Multiply each value by 2 You can

    often use r.row instead of an anonymous function: r.range(5).map(r.row.mul(2))
  10. Query Composition • ReQL embeds natively in your programming language

    • Pass around ReQL expressions like any other code • You can assign ReQL expressions to variables or store them in functions
  11. Understanding ReQL • Anonymous function must return a valid ReQL

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

    • Date and time functions for time data • Support for storing binary objects
  13. Changefeeds • The changes command returns a cursor that receives

    updates • Each update includes the new and old value of the modified record
  14. 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 }
  15. 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' } }
  16. 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
  17. > Client Driver Install the JS client driver from NPM

    in your Node.js project: $ npm install rethinkdb --save
  18. 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() { // Documented inserted }); Add Bob to the “users” table
  19. 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
  20. 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
  21. 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
  22. Client Driver var r = require("rethinkdb"); r.connect().then(function(conn) { return r.table("users")

    .insert({name: “Bob”}) .run(conn, function (err, output) { console.log(output); }) }) Run the query on a connection
  23. 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
  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); }).error(function(err) { console.log("Failed:", err); }); Handle errors emitted by Promise
  25. 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
  26. Using Changefeeds r.connect().then(function(conn) { return r.table("fellowship") .changes().run(conn, function (err, cursor)

    {
 cursor.each(function(err, item) { console.log(item); }); }); Attach a changefeed to the table
  27. 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); }); }); Iterate over every value passed into the cursor
  28. 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
  29. 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
  30. 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
  31. 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
  32. 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
  33. 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
  34. 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
  35. 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
  36. 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
  37. 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
  38. 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
  39. 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