Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Introduction to RethinkDB : DevMountain
Search
Jorge Silva
May 09, 2015
Programming
0
51
Introduction to RethinkDB : DevMountain
Workshop given at Dev Mountain on May 6th, 2015.
Jorge Silva
May 09, 2015
Tweet
Share
More Decks by Jorge Silva
See All by Jorge Silva
Introduction to RethinkDB : Move fast and break things
thejsj
2
250
ForwardJS - RethinkDB - Getting Started
thejsj
0
180
ForwardJS - RethinkDB - Advanced Queries
thejsj
1
190
Automatic Failover in RethinkDB
thejsj
0
220
Workshop: Introduction to RethinkDB : Santa Cruz JS
thejsj
1
110
Push databases: A better way to build realtime apps
thejsj
0
120
Data Modeling in RethinkDB
thejsj
4
260
RethinkDB+Angular.js: Building realtime web applications
thejsj
10
30k
Introduction to RethinkDB: 1KE Meetup
thejsj
0
43
Other Decks in Programming
See All in Programming
テストコード書いてみませんか?
onopon
2
340
令和7年版 あなたが使ってよいフロントエンド機能とは
mugi_uno
11
5.4k
「とりあえず動く」コードはよい、「読みやすい」コードはもっとよい / Code that 'just works' is good, but code that is 'readable' is even better.
mkmk884
6
1.4k
混沌とした例外処理とエラー監視に秩序をもたらす
morihirok
14
2.4k
Rubyでつくるパケットキャプチャツール
ydah
0
180
見えないメモリを観測する: PHP 8.4 `pg_result_memory_size()` とSQL結果のメモリ管理
kentaroutakeda
0
940
ISUCON14感想戦で85万点まで頑張ってみた
ponyo877
1
610
自動で //nolint を挿入する取り組み / Gopher's Gathering
utgwkk
1
110
Асинхронность неизбежна: как мы проектировали сервис уведомлений
lamodatech
0
1.4k
AWS Lambda functions with C# 用の Dev Container Template を作ってみた件
mappie_kochi
0
140
Azure AI Foundryのご紹介
qt_luigi
1
210
盆栽転じて家具となる / Bonsai and Furnitures
aereal
0
1.9k
Featured
See All Featured
Designing for humans not robots
tammielis
250
25k
Unsuck your backbone
ammeep
669
57k
Documentation Writing (for coders)
carmenintech
67
4.5k
Visualizing Your Data: Incorporating Mongo into Loggly Infrastructure
mongodb
44
9.4k
Become a Pro
speakerdeck
PRO
26
5.1k
[Rails World 2023 - Day 1 Closing Keynote] - The Magic of Rails
eileencodes
33
2k
Optimizing for Happiness
mojombo
376
70k
Stop Working from a Prison Cell
hatefulcrawdad
267
20k
Performance Is Good for Brains [We Love Speed 2024]
tammyeverts
7
570
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
98
18k
Design and Strategy: How to Deal with People Who Don’t "Get" Design
morganepeng
127
18k
The Straight Up "How To Draw Better" Workshop
denniskardys
232
140k
Transcript
RethinkDB The database for the realtime web DevMountain Provo, Utah
May 6, 2015
Jorge Silva @thejsj Developer Evangelist @ RethinkDB
Introduction What is RethinkDB?
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
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
RethinkDB Structure Database → Table → Document MySQL: Database →
Table → Row MongoDB: Database → Collection → Document
Sample Document { "name": "Will Riker", "position": "Commander", "height": 193,
"birthdate": Mon Aug 19 2335, "ships": [ { "name": "USS Pegasus" }, { "name": "USS Potemkin" }, { "name": "USS Enterprise" }, ], ... }
Installing RethinkDB http://rethinkdb.com/install/
http://rethinkdb-chat.thejsj.com:10001/ #dataexplorer http://bit.ly/1zMCJH2 Having Issues?
Introduction to ReQL RethinkDB Query Language
Introduction to ReQL • ReQL embeds natively into your programming
language • Compose ReQL queries by chaining commands
Anatomy of a ReQL Query r.table("users") .pluck("last_name") .distinct().count() Number of
unique last names
Anatomy of a ReQL Query r.table("users") .pluck("last_name") .distinct().count() Access a
database table
Anatomy of a ReQL Query r.table("users") .pluck("last_name") .distinct().count() Isolate a
document property
Anatomy of a ReQL Query r.table("users") .pluck("last_name") .distinct().count() Consolidate duplicate
values
Anatomy of a ReQL Query r.table("users") .pluck("last_name") .distinct().count() Display the
number of items
Sample ReQL Queries r.table("users") .filter(r.row("age").gt(30)) r.table("users") .pluck("last_name") .distinct().count() r.table("fellowship") .filter({species:
"hobbit"}) .update({species: "halfling"})
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
Running Queries http://bit.ly/1JQ8imw
Secondary Indexes • Queries performed against indexes are much faster
• Can index on a single property, multiple fields, or arbitrary ReQL expressions
Querying an Index r.table("fellowship") .indexCreate("species") r.table("fellowship") .getAll("human", {index: "species"}) Find
all humans in “fellowship”
Running Queries: Indexes
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:
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))
Running Queries: Functions
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
Running Queries: Query Composition
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
Additional ReQL Features • Geospatial indexing for location- based queries
• Date and time functions for time data • Support for storing binary objects
Realtime Updates Working with Changefeeds
Subscribe to change notifications on database queries Changefeeds
r.table("users").changes() Track changes on the users table Changefeeds
Changefeeds • The changes command returns a cursor that receives
updates • Each update includes the new and old value of the modified record
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 }
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', ... } }
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' } }
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:
Changefeeds r.table("table").get(ID).changes() r.table("table").getAll(ID).changes() r.table("table").between(X, Y).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:
Using Changefeeds
Building Web Apps Using RethinkDB in Node
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
> Client Driver Install the JS client driver from NPM
in your Node.js project: $ npm install rethinkdb --save
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
Tutorial: Building a chat app
#1: Clone the repository git clone
[email protected]
:thejsj/ rethinkdb-workshp.git or https://github.com/thejsj/rethinkdb-
workshop/tarball/master or http://bit.ly/1cmsO0B
#2: Create database and tables (PUPZPVSEBUBFYQMPSFSBOESVO UIFGPMMPXJOHRVFSJFT r.dbCreate(‘chat’); r.db(‘chat’).tableCreate(‘messages’); r.db(‘chat’).tableCreate(‘users’,
{ primaryKey: ‘email’ });
#3: Insert sample data (PUPZPVSEBUBFYQMPSFSBOESVOUIF GPMMPXJOHRVFSZ r.table(‘messages’) .insert(r.json( r.http(‘http://bit.ly/1zMGw7b') ))
r.table(‘users’) .insert(r.json( r.http(‘http://bit.ly/1zBj4tm') ))
#4: Go to server/index.js -PPLGPSUIFDPNNFOUTJOPSEFS UPXSJUFUIFDPSSFDU3F2-RVFSJFT // Step 1 //
Write a query…
Connections *OUIJTBQQ UIFrPCKFDUDPOUBJOT BDPOOFDUJPO r.table(‘messages’).run(r.conn);
Suggestions "EEJOHSPPNTUPDIBUBQQ "EEJOHVTFSTJOSPPNDIBU "EENVMUJQMFOPEFTUPDMVTUFS "EENFTTBHFTFBSDI
"EENFTTBHFMJLJOH 4VQQPSUEFMFUJOHNFTTBHFT 4DIFNBTEFOFEJO3&"%.&
#5: Switch database $POOFDUUPUIFGPMMPXJOH EBUBCBTF TPXFDBOBMMTIBSF NFTTBHFT { host :
‘http://', port : 28015, db : ‘chat’ }
Additional Resources • RethinkDB website: http://rethinkdb.com • RethinkDB cookbook: http://rethinkdb.com/docs/cookbook
• RethinkDB installation: http://rethinkdb.com/docs/install/