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

Workshop: Introduction to RethinkDB : Santa Cruz JS

Workshop: Introduction to RethinkDB : Santa Cruz JS

Jorge Silva

July 09, 2015
Tweet

More Decks by Jorge Silva

Other Decks in Programming

Transcript

  1. RethinkDB
    The database for the
    realtime web
    Santa Cruz JS
    Santa Cruz, California
    July 9, 2015

    View Slide

  2. Jorge Silva
    @thejsj
    Developer Evangelist @ RethinkDB

    View Slide

  3. 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

    View Slide

  4. Introduction
    What is RethinkDB?

    View Slide

  5. 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

    View Slide

  6. 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

    View Slide

  7. 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

    View Slide

  8. Power and Convenience
    • Highly expressive query language
    • Relational features like table joins
    • Powerful admin UI with point-
    and-click cluster management

    View Slide

  9. RethinkDB Structure
    Database → Table → Document
    MySQL: Database → Table → Row
    MongoDB: Database → Collection → Document

    View Slide

  10. Sample Document
    {
    "name": "Will Riker",
    "position": "Commander",
    "height": 193,
    "birthdate": Mon Aug 19 2335,
    "ships": [
    { "name": "USS Pegasus" },
    { "name": "USS Potemkin" },
    { "name": "USS Enterprise" },
    ],
    ...
    }

    View Slide

  11. 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

    View Slide

  12. Differences with MongoDB
    • RethinkDB supports joins and
    subqueries
    • MongoDB only supports the
    traditional query-response model.
    You can't subscribe to queries.

    View Slide

  13. Introduction to ReQL
    RethinkDB query language

    View Slide

  14. Introduction to ReQL
    • ReQL embeds natively into your
    programming language
    • Compose ReQL queries by
    chaining commands

    View Slide

  15. Anatomy of a ReQL Query
    r.table("users")
    .pluck("last_name")
    .distinct().count()
    Number of unique last names

    View Slide

  16. Anatomy of a ReQL Query
    r.table("users")
    .pluck("last_name")
    .distinct().count()
    Access a database table

    View Slide

  17. Anatomy of a ReQL Query
    r.table("users")
    .pluck("last_name")
    .distinct().count()
    Isolate a document property

    View Slide

  18. Anatomy of a ReQL Query
    r.table("users")
    .pluck("last_name")
    .distinct().count()
    Consolidate duplicate values

    View Slide

  19. Anatomy of a ReQL Query
    r.table("users")
    .pluck("last_name")
    .distinct().count()
    Display the number of items

    View Slide

  20. Sample ReQL Queries
    r.table("users")
    .filter(r.row("age").gt(30))
    r.table(“posts")
    .eqJoin(“userId”, r.table(“users”))
    .zip()
    r.table("posts")
    .filter({status: "draft"})
    .update({status: "published"})

    View Slide

  21. 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

    View Slide

  22. 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

    View Slide

  23. 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

    View Slide

  24. 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

    View Slide

  25. 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

    View Slide

  26. 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

    View Slide

  27. Additional ReQL Features
    • Geospatial indexing for location-
    based queries
    • Date and time functions
    • Support for storing binary objects
    • Execute http requests using r.http

    View Slide

  28. Running Queries
    https://github.com/thejsj/rethinkdb-workshop

    View Slide

  29. http://rethinkdb.thejsj.com:8080
    Running Queries

    View Slide

  30. Realtime Updates
    Working with Changefeeds

    View Slide

  31. Subscribe to change notifications
    on database queries
    Changefeeds

    View Slide

  32. r.table("users").changes()
    Track changes on the users table
    Changefeeds

    View Slide

  33. Changefeeds
    • The changes command returns a
    cursor that receives updates
    • Each update includes the new and
    old value of the modified record

    View Slide

  34. 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
    }

    View Slide

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

    View Slide

  36. 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'
    }
    }

    View Slide

  37. Changefeeds
    r.table("players")
    .orderBy({index: r.desc("score")})
    .limit(3).changes()
    Track top three players by score
    Chain the changes command
    to an actual ReQL query:

    View Slide

  38. 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:

    View Slide

  39. Using Changefeeds

    View Slide

  40. Building Web Apps
    Using RethinkDB in Node

    View Slide

  41. 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

    View Slide

  42. >
    Client Driver
    Install the JS client driver from
    npm in your Node.js project:
    $ npm install rethinkdb --save

    View Slide

  43. 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() {
    // Document inserted
    });
    Add Bob to the “users” table

    View Slide

  44. 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

    View Slide

  45. 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

    View Slide

  46. 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

    View Slide

  47. 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

    View Slide

  48. 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

    View Slide

  49. 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

    View Slide

  50. 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

    View Slide

  51. 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);
    });
    });

    View Slide

  52. 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);
    });
    });

    View Slide

  53. 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

    View Slide

  54. 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

    View Slide

  55. 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

    View Slide

  56. 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

    View Slide

  57. 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

    View Slide

  58. 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

    View Slide

  59. 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

    View Slide

  60. Socket.io (Client)


    Real-time web app

    <br/>var socket = io.connect();<br/>socket.on("update", function(data) {<br/>console.log("Update:", data);<br/>});<br/>Receive Socket.io updates on frontend<br/>

    View Slide

  61. Socket.io (Client)


    Real-time web app

    <br/>var socket = io.connect();<br/>socket.on("update", function(data) {<br/>console.log("Update:", data);<br/>});<br/>Load the Socket.io client script<br/>

    View Slide

  62. Socket.io (Client)


    Real-time web app

    <br/>var socket = io.connect();<br/>socket.on("update", function(data) {<br/>console.log("Update:", data);<br/>});<br/>Connect to the Socket.io server<br/>

    View Slide

  63. Socket.io (Client)


    Real-time web app

    <br/>var socket = io.connect();<br/>socket.on("update", function(data) {<br/>console.log("Update:", data);<br/>});<br/>Create handler for “update” messages<br/>

    View Slide

  64. Socket.io (Client)


    Real-time web app

    <br/>var socket = io.connect();<br/>socket.on("update", function(data) {<br/>console.log("Update:", data);<br/>});<br/>Display update in browser console<br/>

    View Slide

  65. Tutorial: Building a chat app

    View Slide

  66. #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

    View Slide

  67. #2: Install Dependencies
    // Go to the project directory
    cd rethinkdb-workshop
    // Install dependencies
    npm install

    View Slide

  68. #3: Go to config/default.js
    6QEBUFZPVS3FUIJOL%#EBUBCBTF
    DPOHVSBUJPO
    var config = {
    "rethinkdb": {
    "host": "localhost", // or rethinkdb.thejsj.com
    "port": 29015,
    "db" : "rethinkdb_workshop"
    // or GITHUB_HANDLE_rethinkdb_workshop
    },

    View Slide

  69. #4: Run Server
    // Start server
    npm run dev // or `node server`

    View Slide

  70. #4: Go to server/index.js
    -PPLGPSUIFDPNNFOUTJOPSEFS
    UPXSJUFUIFDPSSFDU3F2-RVFSJFT
    // Step 1
    // Write a query

    View Slide

  71. Connections
    *OUIJTBQQ UIF`r`PCKFDU
    DPOUBJOTBDPOOFDUJPO
    r.table("messages").run(r.conn);

    View Slide

  72. #5: Switch database
    $POOFDUUPUIFGPMMPXJOHEBUBCBTF TPXF
    DBOBMMTIBSFNFTTBHFT
    var config = {
    "rethinkdb": {
    "host": "rethinkdb.thejsj.com",
    "port": 29015,
    "db" : "GITHUB_HANDLE_rethinkdb_workshop"
    },

    View Slide

  73. Next steps
    • Advanced Commands: `r.do`,
    `r.branch`, `r.forEach`
    • Map/Reduce queries
    • Indexes (multi, compound, index
    functions, geospatial)
    • Sharding and replication

    View Slide

  74. Questions
    • RethinkDB website:

    http://rethinkdb.com
    • Install RethinkDB:

    http://rethinkdb.com/install/
    • Email me: [email protected]
    • Tweet: @thejsj, @rethinkdb

    View Slide