Drivers

This section deep down a bit on how the drivers work, you can skip if you are not interested in how RethinkDB driver works at low level. But I really hope you keep reading it. Let’s start.

ReQL is binded to your language. Therefore, the API is implemented totally by the driver itself. You won’t work directly with RethinkDB server. You write the query using the API of driver, the driver will built it into a real query to send to server, receive data, parse it to return data as a native data of your language.

Internaly, all client driver will turn the query that you write in driver language into an AST tree, then serialize them as JSON and send to server.

If you curious, you can fire up tcpdump and watch the raw query in JSON

1 tcpdump -nl -w - -i lo0 -c 500 port 28015|strings

An example of what above tcpdump return when I run those command(in Ruby):

1 r.db("foodb").table("users").with_fields("address").run

Once I ran this command, I see this via tcpdump:

[1,[96,[[15,[[14,[“foodb”]],”users”]],”address”]],{}]

So basically, the whole query is turned into a special JSON object by client driver. If you would like to dig deeper, the above query is actually translate in to this:

[QUERY_START, [WITH_FIELDS, [[TABLE, [[DB, [“foodb”]],”users”]],”address”]],{}]

Each of numbers is equivalent to a command in RethinkDB. Those number is predefined in RethinkDB. So basically, whatever you write using client driver API will be turn into an JSON array. Each of element often takes this form:

1 COMMAND, [Argument Array], {Option object}

It’s similar to a function call when we have function name, follow by its argument and the last is an option object.

You can quickly sense a downside is that each of driver have different API to construct query. When you come to another language, you may feel very strange. The driver hide the real query behinds its API. It’s kind of similar to how you use an ORM in SQL world to avoid writing raw SQL string. But it’s different because the ORM usually has its own API to turn query into raw query string, which in turns send to server using another driver with that database protocol. Here, we are having power of an ORM, but happen at driver level, because RethinkDB protocol is a powerful JSON protocol to help model query like function call, with argument and follow by parameter. In fact, ReQL is modeled after functional languages like Lisp or Hashkell.

If you would like to know more about ReQL at lower level, you should read more in official documents

Using drivers

RethinkDB supports 3 official drives:

  • Ruby
  • NodeJS
  • Python

These support all driver specifications. The community drives such as Go, PHP probably won’t support them all, if you used a different language and find something isn’t right, it is probably not your fault.

All ReQL starts with r, its top level module to expose its public API. In NodeJS, we can use

1 var r = require('rethinkdb')

or Ruby

1 require 'rethinkdb'
2 include RethinkDB::Shortcuts
3 puts r.inspect

or in Go Lang

1 import (
2   r "github.com/dancannon/gorethink"
3 )

Once we constructed ReQL with r, we have to call run method to execute it. The command will be submit to an active database connection. The database connection can be establish with connect.

1 var r = require('rethinkdb')
2 var connection = r.connect({
3   host: '127.0.0.1', 
4   port: '28015', 
5   db: 'test'
6 }, function (err, conn) {
7   r.db('db').table('table').filter({type: 'anime'})
8 })

When creating the connection with r.connect, you can pass an db parameter to specify a default database to work on once connecting succesfully. It’s similar to the current database of MySQL. Without setting this parameter, RethinkDB assumes test as default database.

To understand more about difference of API in different language, let looks at Go Lang driver1

Notice that we don’t have any host, or database parameter now. They are Addressand Database in Go Lang driver. Therefore, by using an un-official language, the API will be totally different with official API.

That’s how beautiful it is because each language has its own design philosophy. Such as in Go lang, we cannot have a lower case field of a struct and expect it publicly available to outside. Using names such as host or db for connection option is impossible in Go lang.

Default database

Similar to MySQL, when you can issue use database_name to switch to another database. We can do that in RethinkDB by calling use command on a connection object.

1 connection.use('another_db')

In this small book, most of the time, we will use Data Exploer. Therefore we can use r without initialization and calling run method. Data Exploer will do that for us. Just keep in mind when you write code, you have to connect, and explicitly call run to, obviously, run the query.

Note that you don’t have to switch to another database to access its table, you can just call r.db('another_db') before building query.

Repl

Repl means read-eval-print loop. To avoid burden of manually call run and passing connection object. Some driver offers a repl to help call run without any parameter.

Such as in Ruby:

1 r.connect(:db => 'marvel').repl
2 r.table("test").run

JavaScript doesn’t have a repl. I think because we can already used the Data Explorer.

  1. https://github.com/dancannon/gorethink

    var connection *r.Session

    connection, err := r.Connect(r.ConnectOpts{ Address: “localhost:28015”, Database: “test”, })

    if err != nil { log.Fatalln(err.Error()) }