feathers-rethinkdb is a database adapter for RethinkDB, a real-time database.
$ npm install --save rethinkdbdash feathers-rethinkdb
Important:
feathers-rethinkdb
implements the Feathers Common database adapter API and querying syntax.
This adapter requires a running RethinkDB server.
Returns a new service instance initialized with the given options. For more information on initializing the driver see the RethinkDBdash documentation.
const r = require('rethinkdbdash')({
db: 'feathers'
});
const service = require('feathers-rethinkdb');
app.use('/messages', service({
Model: r,
db: 'someotherdb', //must be on the same connection as rethinkdbdash
name: 'messages',
// Enable pagination
paginate: {
default: 2,
max: 4
}
}));
Note: By default,
watch
is set totrue
which means this adapter monitors the database for changes and automatically sends real-time events. This means that, unlike other databases and services, you will also get events if the database is changed directly.
Options:
Model
(required) - Therethinkdbdash
instance, already initialized with a configuration object. see options herename
(required) - The name of the tablewatch
(optional, default:true
) - Listen to table changefeeds and send according real-time events on the adapter.db
(optional, default:none
) - Specify and alternate rethink database for the service to use. Must be on the same server/connection used by rethinkdbdash. It will be auto created if you call init() on the service and it does not yet exist.id
(optional, default:'id'
) - The name of the id field property. Needs to be set as the primary key when creating the table.events
(optional) - A list of custom service events sent by this servicepaginate
(optional) - A pagination object containing adefault
andmax
page size
Create the database and table if it does not exists. options
can be the RethinkDB tableCreate options.
// Initialize the `messages` table with `messageId` as the primary key
app.service('messages').init({
primaryKey: 'messageId'
}).then(() => {
// Use service here
});
Returns a RethinkDB query with the common filter criteria (without pagination) applied.
When making a service method call, params
can contain an rethinkdb
property which allows to pass additional RethinkDB options. See customizing the query for an example.
To run the complete RethinkDB example we need to install
$ npm install @feathersjs/feathers @feathersjs/errors @feathersjs/express @feathersjs/socketio feathers-rethinkdb rethinkdbdash
We also need access to a RethinkDB server. You can install a local server on your local development machine by downloading one of the packages from the RethinkDB website. It might also be helpful to review their docs on starting a RethinkDB server.
Then add the following into app.js
:
const feathers = require('@feathersjs/feathers');
const express = require('@feathersjs/express');
const socketio = require('@feathersjs/socketio');
const rethink = require('rethinkdbdash');
const service = require('feathers-rethinkdb');
// Connect to a local RethinkDB server.
const r = rethink({
db: 'feathers'
});
// Create an Express compatible Feathers applicaiton instance.
const app = express(feathers());
// Turn on JSON parser for REST services
app.use(express.json());
// Turn on URL-encoded parser for REST services
app.use(express.urlencoded({extended: true}));
// Enable the REST provider for services.
app.configure(express.rest());
// Enable the socketio provider for services.
app.configure(socketio());
// Register the service
app.use('messages', service({
Model: r,
name: 'messages',
paginate: {
default: 10,
max: 50
}
}));
app.use(express.errorHandler());
// Initialize database and messages table if it does not exists yet
app.service('messages').init().then(() => {
// Create a message on the server
app.service('messages').create({
text: 'Message created on server'
}).then(message => console.log('Created message', message));
const port = 3030;
app.listen(port, function() {
console.log(`Feathers server listening on port ${port}`);
});
});
Run the example with node app
and go to localhost:3030/messages.
In addition to the common querying mechanism, this adapter also supports:
Return all matches for a property using the RethinkDB match syntax.
// Find all messages starting with Hello
app.service('messages').find({
query: {
text: {
$search: '^Hello'
}
}
});
// Find all messages ending with !
app.service('messages').find({
query: {
text: {
$search: '!$'
}
}
});
GET /messages?text[$search]=^Hello
GET /messages?text[$search]=!$
Matches if the property is an array that contains the given entry.
// Find all messages tagged with `nodejs`
app.service('messages').find({
query: {
tags: {
$contains: 'nodejs'
}
}
});
GET /messages?tags[$contains]=nodejs
Matches if the document contains a nested property that fits the query
Given the following document structure
app.service('people').create([{
name: 'Dave',
postalAddress: {
city: 'Melbourne',
country: 'US',
state: 'FL',
street: '123 6th St',
zipcode: '32904'
}
}, {
name: 'Tom',
postalAddress: {
city: 'Chevy Chase',
country: 'US',
state: 'MD',
street: '71 Pilgrim Avenue',
zipcode: '20815'
}
}, {
name: 'Eric',
postalAddress: {
city: 'Honolulu',
country: 'US',
state: 'HI',
street: '4 Goldfield St',
zipcode: '96815'
}
}])
// Find all people with postalAddress.state that starts with `F`
app.service('people').find({
query: {
'postalAddress.state': {
$search: '^F'
}
}
}
});
GET /people?postalAddress.state[$search]=^F
In a find
call, params.rethinkdb
can be passed a RethinkDB query (without pagination) to customize the find results.
Combined with .createQuery(query)
, which returns a new RethinkDB query with the common filter criteria applied, this can be used to create more complex queries. The best way to customize the query is in a before hook for find
. The following example adds a coerceTo
condition from RethinkDB coerceTo API to match by any string inside an object.
app.service('mesages').hooks({
before: {
find(context) {
const query = context.service.createQuery(context.params.query);
const searchString = "my search string";
hook.params.rethinkdb = query.filter(function(doc) {
return doc.coerceTo('string').match('(?i)' + searchString);
})
}
}
});
If you need even more control then you can use service.table
(context.service.table
in a hook) directly. This way you can create a query from scratch without the the common filter criteria applied. The following example adds a getNearest
condition for RethinkDB geospatial queries.
app.service('mesages').hooks({
before: {
find(context) {
const r = this.options.r;
const point = r.point(-122.422876, 37.777128); // San Francisco
// Replace the query with a custom query
context.params.rethinkdb = context.service.table.getNearest(point, { index: 'location' });
}
}
});
.createQuery(query)
can also be used to listen to changefeeds and then send custom events.
Since the service already sends real-time events for all changes the recommended way to listen to changes is with feathers-reactive however.
Copyright (c) 2017
Licensed under the MIT license.