{"id":13527226,"url":"https://github.com/neumino/rethinkdbdash","last_synced_at":"2025-05-15T09:00:28.421Z","repository":{"id":13243242,"uuid":"15928042","full_name":"neumino/rethinkdbdash","owner":"neumino","description":"An advanced Node.js driver for RethinkDB with a connection pool, support for streams etc.","archived":false,"fork":false,"pushed_at":"2022-05-06T22:40:39.000Z","size":1604,"stargazers_count":843,"open_issues_count":53,"forks_count":108,"subscribers_count":25,"default_branch":"master","last_synced_at":"2025-05-11T15:37:47.716Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/neumino.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-01-15T07:27:19.000Z","updated_at":"2025-05-03T22:00:42.000Z","dependencies_parsed_at":"2022-09-16T23:51:51.528Z","dependency_job_id":null,"html_url":"https://github.com/neumino/rethinkdbdash","commit_stats":null,"previous_names":[],"tags_count":150,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/neumino%2Frethinkdbdash","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/neumino%2Frethinkdbdash/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/neumino%2Frethinkdbdash/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/neumino%2Frethinkdbdash/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/neumino","download_url":"https://codeload.github.com/neumino/rethinkdbdash/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254310509,"owners_count":22049467,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-01T06:01:43.582Z","updated_at":"2025-05-15T09:00:28.369Z","avatar_url":"https://github.com/neumino.png","language":"JavaScript","readme":"rethinkdbdash\n-------------\n\n\u003ca href=\"https://app.wercker.com/project/bykey/10e69719c2031f4995798ddb9221c398\"\u003e\u003cimg alt=\"Wercker status\" src=\"https://app.wercker.com/status/10e69719c2031f4995798ddb9221c398/m/master\" align=\"right\" /\u003e\u003c/a\u003e\n\nA Node.js driver for RethinkDB with more advanced features.\n\n### Install\n\n```\nnpm install rethinkdbdash\n```\n\n_Note_: The `rethinkdbdash-unstable` package is a relic from the past (rethinkdb \u003c 1.13).\n\n### Quick start\n\nRethinkdbdash uses almost the same API as the official driver. Please refer to\nthe [official driver's documentation](http://www.rethinkdb.com/api/javascript/)\nfor all the ReQL methods (the methods used to build the query).\n\n\nThe main differences are:\n\n- You need to execute the module when you import it:\n\n```js\nvar r = require('rethinkdbdash')();\n// With the official driver:\n// var r = require('rethinkdb');\n```\n\n- Connections are managed by the driver with an efficient connection pool.\nOnce you have imported the driver, you can immediately run queries,\nyou don't need to call `r.connect`, or pass a connection to `run`.\n\n```js\nvar r = require('rethinkdbdash')();\nr.table('users').get('orphee@gmail.com').run().then(function(user) {\n  // ...\n}).error(handleError)\n```\n\n- Cursors are coerced to arrays by default\n\n```js\nvar r = require('rethinkdbdash')();\nr.table('data').run().then(function(result) {\n  assert(Array.isArray(result)) // true\n  // With the official driver you need to call\n  // result.toArray().then(function(result2) {\n  //   assert(Array.isArray(result2))\n  // })\n});\n```\n\n#### Drop in\n\nYou can replace the official driver with rethinkdbdash by just replacing\n\n```js\nvar r = require('rethinkdb');\n```\n\nWith:\n\n```js\nvar r = require('rethinkdbdash')({\n  pool: false,\n  cursor: true\n});\n```\n\nIf you want to take advantage of the connection pool, refer to the next section.\n\n\n#### From the official driver\n\nTo switch from the official driver to rethinkdbdash and get the most of it,\nhere are the few things to do:\n\n1. Change the way to import the driver.\n\n  ```js\n  var r = require('rethinkdb');\n  ```\n\n  To:\n\n  ```js\n  var r = require('rethinkdbdash')();\n  // Or if you do not connect to the default local instance:\n  // var r = require('rethinkdbdash')({servers: [{host: ..., port: ...}]});\n  ```\n\n2. Remove everything related to a connection:\n\n  ```js\n  r.connect({host: ..., port: ...}).then(function(connection) {\n    connection.on('error', handleError);\n    query.run(connection).then(function(result) {\n      // console.log(result);\n      connection.close();\n    });\n  });\n  ```\n\n  Becomes:\n\n  ```js\n  query.run().then(function(result) {\n    // console.log(result);\n  });\n  ```\n\n3. Remove the methods related to the cursor. This typically involves\nremoving `toArray`:\n\n  ```js\n  r.table('data').run(connection).then(function(cursor) {\n    cursor.toArray().then(function(result) {\n      // console.log(result):\n    });\n  });\n  ```\n\n  Becomes\n\n  ```js\n  r.table('data').run().then(function(result) {\n    // console.log(result);\n  });\n  ```\n\n\n#### Using TLS Connections\n\n_Note_: Support for a TLS proxy is experimental.\n\nRethinkDB does not support TLS connections to the server yet, but in case you want\nto run it over an untrusted network and need encryption, you can easily run a TLS proxy\non your server with:\n\n```js\nvar tls = require('tls');\nvar net = require('net');\nvar tlsOpts = {\n  key: '', // You private key\n  cert: '' // Public certificate\n};\ntls.createServer(tlsOpts, function (encryptedConnection) {\n  var rethinkdbConn = net.connect({\n    host: 'localhost',\n    port: 28015\n  });\n  encryptedConnection.pipe(rethinkdbConn).pipe(encryptedConnection);\n}).listen(29015);\n```\n\nAnd then safely connect to it with the `tls` option:\n\n```js\nvar r = require('rethinkdbdash')({\n  port: 29015,\n  host: 'place-with-no-firewall.com',\n  ssl: true\n});\n```\n\n`ssl` may also be an object that will be passed as the `options` argument to\n[`tls.connect`](http://nodejs.org/api/tls.html#tls_tls_connect_options_callback).\n\n\n### New features and differences\n\nRethinkdbdash ships with a few interesting features.\n\n\n#### Importing the driver\n\nWhen you import the driver, as soon as you execute the module, you will create\na default connection pool (except if you pass `{pool: false}`. The options you\ncan pass are:\n\n- `db`: `\u003cstring\u003e` - The default database to use if none is mentioned.\n- `user`: `\u003cstring\u003e` - The RethinkDB user, default value is admin.\n- `password`: `\u003cstring\u003e` - The password for the user, default value is an empty string.\n- `discovery`: `\u003cboolean\u003e` - When true, the driver will regularly pull data from the table `server_status` to\nkeep a list of updated hosts, default `false`\n- `pool`: `\u003cboolean\u003e` - Set it to `false`, if you do not want to use a connection pool.\n- `buffer`: `\u003cnumber\u003e` - Minimum number of connections available in the pool, default `50`\n- `max`: `\u003cnumber\u003e` - Maximum number of connections available in the pool, default `1000`\n- `timeout`: `\u003cnumber\u003e` - The number of seconds for a connection to be opened, default `20`\n- `pingInterval`: \u003cnumber\u003e - if `\u003e 0`, the connection will be pinged every `pingInterval` seconds, default `-1`\n- `timeoutError`: `\u003cnumber\u003e` - Wait time before reconnecting in case of an error (in ms), default 1000\n- `timeoutGb`: `\u003cnumber\u003e` - How long the pool keep a connection that hasn't been used (in ms), default 60\\*60\\*1000\n- `maxExponent`: `\u003cnumber\u003e` - The maximum timeout before trying to reconnect is 2^maxExponent x timeoutError, default 6 (~60 seconds for the longest wait)\n- `silent`: \u003cboolean\u003e - console.error errors, default `false`\n- `servers`: an array of objects `{host: \u003cstring\u003e, port: \u003cnumber\u003e}` representing RethinkDB nodes to connect to\n- `optionalRun`: \u003cboolean\u003e - if `false`, yielding a query will not run it, default `true`\n- `log`: \u003cfunction\u003e - will be called with the log events by the pool master\n\nIn case of a single instance, you can directly pass `host` and `port` in the top level parameters.\n\nExamples:\n\n```js\n// connect to localhost:8080, and let the driver find other instances\nvar r = require('rethinkdbdash')({\n    discovery: true\n});\n\n// connect to and only to localhost:8080\nvar r = require('rethinkdbdash')();\n\n// Do not create a connection pool\nvar r = require('rethinkdbdash')({pool: false});\n\n// Connect to a cluster seeding from `192.168.0.100`, `192.168.0.101`, `192.168.0.102`\nvar r = require('rethinkdbdash')({\n    servers: [\n        {host: '192.168.0.100', port: 28015},\n        {host: '192.168.0.101', port: 28015},\n        {host: '192.168.0.102', port: 28015},\n    ]\n});\n\n// Connect to a cluster containing `192.168.0.100`, `192.168.0.100`, `192.168.0.102` and\n// use a maximum of 3000 connections and try to keep 300 connections available at all time.\nvar r = require('rethinkdbdash')({\n    servers: [\n        {host: '192.168.0.100', port: 28015},\n        {host: '192.168.0.101', port: 28015},\n        {host: '192.168.0.102', port: 28015},\n    ],\n    buffer: 300,\n    max: 3000\n});\n```\n\nYou can also pass `{cursor: true}` if you want to retrieve RethinkDB streams as cursors\nand not arrays by default.\n\n_Note_: The option `{stream: true}` that asynchronously returns a stream is deprecated. Use `toStream` instead.\n\n_Note_: The option `{optionalRun: false}` will disable the optional run for all instances of the driver.\n\n_Note_: Connections are created with TCP keep alive turned on, but some routers seem to ignore this setting. To make\nsure that your connections are kept alive, set the `pingInterval` to the interval in seconds you want the\ndriver to ping the connection.\n\n_Note_: The error `__rethinkdbdash_ping__` is used for internal purposes (ping). Do not use it.\n\n#### Connection pool\n\nAs mentioned before, `rethinkdbdash` has a connection pool and manage all the connections\nitself. The connection pool is initialized as soon as you execute the module.\n\nYou should never have to worry about connections in rethinkdbdash. Connections are created\nas they are needed, and in case of a host failure, the pool will try to open connections with an\nexponential back off algorithm.\n\nThe driver execute one query per connection. Now that [rethinkdb/rethinkdb#3296](https://github.com/rethinkdb/rethinkdb/issues/3296)\nis solved, this behavior may be changed in the future.\n\nBecause the connection pool will keep some connections available, a script will not\nterminate. If you have finished executing your queries and want your Node.js script\nto exit, you need to drain the pool with:\n\n```js\nr.getPoolMaster().drain();\n```\n\nThe pool master by default will log all errors/new states on `stderr`. If you do not\nwant to pollute `stderr`, pass `silent: true` when you import the driver and\nprovide your own `log` method.\n\n```js\nr = require('rethinkdbdash')({\n  silent: true,\n  log: function(message) {\n    console.log(message);\n  }\n});\n```\n\n##### Advanced details about the pool\n\nThe pool is composed of a `PoolMaster` that retrieve connections for `n` pools where `n` is the number of\nservers the driver is connected to. Each pool is connected to a unique host.\n\nTo access the pool master, you can call the method `r.getPoolMaster()`.\n\nThe pool emits a few events:\n- `draining`: when `drain` is called\n- `queueing`: when a query is added/removed from the queue (queries waiting for a connection), the size of the queue is provided\n- `size`: when the number of connections changes, the number of connections is provided\n- `available-size`: when the number of available connections changes, the number of available connections is provided\n\nYou can get the number of connections (opened or being opened).\n```js\nr.getPoolMaster().getLength();\n```\n\nYou can also get the number of available connections (idle connections, without\na query running on it).\n\n```js\nr.getPoolMaster().getAvailableLength();\n```\n\nYou can also drain the pool as mentionned earlier with;\n\n```js\nr.getPoolMaster().drain();\n```\n\nYou can access all the pools with:\n```js\nr.getPoolMaster().getPools();\n```\n\nThe pool master emits the `healthy` when its state change. Its state is defined as:\n- healthy when at least one pool is healthy: Queries can be immediately executed or will be queued.\n- not healthy when no pool is healthy: Queries will immediately fail.\n\nA pool being healthy is it has at least one available connection, or it was just\ncreated and opening a connection hasn't failed.\n\n```js\nr.getPoolMaster().on('healthy', function(healthy) {\n  if (healthy === true) {\n    console.log('We can run queries.');\n  }\n  else {\n    console.log('No queries can be run.');\n  }\n});\n```\n\n\n##### Note about connections\n\nIf you do not wish to use rethinkdbdash connection pool, you can implement yours. The\nconnections created with rethinkdbdash emits a \"release\" event when they receive an\nerror, an atom, or the end (or full) sequence.\n\nA connection can also emit a \"timeout\" event if the underlying connection times out.\n\n\n#### Arrays by default, not cursors\n\nRethinkdbdash automatically coerce cursors to arrays. If you need a raw cursor,\nyou can call the `run` command with the option `{cursor: true}` or import the\ndriver with `{cursor: true}`.\n\n```js\nr.expr([1, 2, 3]).run().then(function(result) {\n  console.log(JSON.stringify(result)) // print [1, 2, 3]\n})\n```\n\n```js\nr.expr([1, 2, 3]).run({cursor: true}).then(function(cursor) {\n  cursor.toArray().then(function(result) {\n    console.log(JSON.stringify(result)) // print [1, 2, 3]\n  });\n})\n```\n\n__Note__: If a query returns a cursor, the connection will not be\nreleased as long as the cursor hasn't fetched everything or has been closed.\n\n\n#### Readable streams\n\n[Readable streams](http://nodejs.org/api/stream.html#stream_class_stream_readable) can be\nsynchronously returned with the `toStream([connection])` method.\n\n```js\nvar fs = require('fs');\nvar file = fs.createWriteStream('file.txt');\n\nvar r = require('rethinkdbdash')();\nr.table('users').toStream()\n  .on('error', console.log)\n  .pipe(file)\n  .on('error', console.log)\n  .on('end', function() {\n    r.getPool().drain();\n  });\n```\n\n_Note:_ The stream will emit an error if you provide it with a single value (streams, arrays\nand grouped data work fine).\n\n_Note:_ `null` values are currently dropped from streams.\n\n#### Writable and Transform streams\n\nYou can create a [Writable](http://nodejs.org/api/stream.html#stream_class_stream_writable)\nor [Transform](http://nodejs.org/api/stream.html#stream_class_stream_transform) streams by\ncalling `toStream([connection, ]{writable: true})` or\n`toStream([connection, ]{transform: true})` on a table.\n\nBy default, a transform stream will return the saved documents. You can return the primary\nkey of the new document by passing the option `format: 'primaryKey'`.\n\nThis makes a convenient way to dump a file your database.\n\n```js\nvar file = fs.createReadStream('users.json')\nvar table = r.table('users').toStream({writable: true});\n\nfile.pipe(transformer) // transformer would be a Transform stream that splits per line and call JSON.parse\n    .pipe(table)\n    .on('finish', function() {\n        console.log('Done');\n        r.getPool().drain();\n    });\n```\n\n\n#### Optional `run` with `yield`\n\nThe `then` and `catch` methods are implemented on a `Term` - returned by any methods\nlike `filter`, `update` etc. They are shortcut for `this.run().then(callback)` and\n`this.run().catch(callback)`.\n\nThis means that you can `yield` any query without calling `run.`\n\n```js\nvar bluebird = require('bluebird');\nvar r = require('rethinkdbdash')();\n\nbluebird.coroutine(function*() {\n  try {\n    var result = yield r.table('users').get('orphee@gmail.com').update({name: 'Michel'});\n    assert.equal(result.errors, 0);\n  } catch(err) {\n    console.log(err);\n  }\n});\n```\n\n_Note_: You have to start Node \u003e= 0.11 with the `--harmony` flag.\n\n\n#### Global default values\n\nYou can set the maximum nesting level and maximum array length on all your queries with:\n\n```js\nr.setNestingLevel(\u003cnumber\u003e)\n```\n\n```js\nr.setArrayLimit(\u003cnumber\u003e)\n```\n\n#### Undefined values\n\nRethinkdbdash will ignore the keys/values where the value is `undefined` instead\nof throwing an error like the official driver.\n\n\n#### Better errors\n\n\n##### Backtraces\n\nIf your query fails, the driver will return an error with a backtrace; your query\nwill be printed and the broken part will be highlighted.\n\nBacktraces in rethinkdbdash are tested and properly formatted. Typically, long backtraces\nare split on multiple lines and if the driver cannot serialize the query,\nit will provide a better location of the error.\n\n\n##### Arity errors\n\nThe server may return confusing error messages when the wrong number\nof arguments is provided (See [rethinkdb/rethinkdb#2463](https://github.com/rethinkdb/rethinkdb/issues/2463) to track progress).\nRethinkdbdash tries to make up for it by catching errors before sending\nthe query to the server if possible.\n\n\n#### Performance\n\nThe tree representation of the query is built step by step and stored which avoid\nrecomputing it if the query is re-run.  \n\nThe code was partially optimized for v8, and is written in pure JavaScript which avoids\nerrors like [issue #2839](https://github.com/rethinkdb/rethinkdb/issues/2839)\n\n\n### Run tests\n\nUpdate `test/config.js` if your RethinkDB instance doesn't run on the default parameters.\n\nMake sure you run a version of Node that supports generators and run:\n```\nnpm test\n```\n\nLonger tests for the pool:\n\n```\nmocha long_test/discovery.js -t 50000\nmocha long_test/static.js -t 50000\n```\n\n\nTests are also being run on [wercker](http://wercker.com/):\n- Builds: [https://app.wercker.com/#applications/52dffe8ba4acb3ef16010ef8/tab](https://app.wercker.com/#applications/52dffe8ba4acb3ef16010ef8/tab)\n- Box: \n  - Github: [https://github.com/neumino/box-rethinkdbdash](https://github.com/neumino/box-rethinkdbdash)\n  - Wercker builds: [https://app.wercker.com/#applications/52dffc65a4acb3ef16010b60/tab](https://app.wercker.com/#applications/52dffc65a4acb3ef16010b60/tab)\n\n\n### FAQ\n\n- __Why rethinkdbdash?__\n\n  Rethinkdbdash was built as an experiment for promises and a connection pool. Its\n  purpose was to test new features and improve the official driver. Today,\n  rethinkdbdash still tries to make the developer experience as pleasant as possible -\n  like with the recent support for Node.js streams.\n\n  Some features like promises have been back ported to the official driver, some like\n  the connection pool and streams are on their way.\n\n\n- __Is it stable?__\n\n  Yes. Rethinkdbdash is used by quite many people. The driver is also used by `thinky`,\n  and has been and is still being tested in the wild.\n\n\n- __Does it work with io.js?__\n\n  All the tests pass with io.js so yes.\n\n\n- __Is rethinkdbdash going to become the JavaScript official driver?__\n\n  Not (yet?), maybe :)\n\n  Completely replacing the driver requires some work:\n  - Integrate the driver in RethinkDB suite test.\n  - Support HTTP connections.\n  - Rollback some default like the coercion of cursors to arrays.\n\n\n- __Can I contribute?__\n\n  Feel free to send a pull request. If you want to implement a new feature, please open\n  an issue first, especially if it's a non backward compatible one.\n\n### Browserify\n\nTo build the browser version of rethinkdbdash, run:\n\n```\nnode browserify.js\n```\n","funding_links":[],"categories":["Repository","JavaScript","others","Awesome RethinkDB [![Awesome](https://cdn.rawgit.com/sindresorhus/awesome/d7305f38d29fed78fa85652e3a63e154dd8e8829/media/badge.svg)](https://github.com/sindresorhus/awesome)"],"sub_categories":["Database","Table of Contents"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fneumino%2Frethinkdbdash","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fneumino%2Frethinkdbdash","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fneumino%2Frethinkdbdash/lists"}