Building Better Node.js Applications with RethinkDB
nodecraft.com
nodecraft.com
Congratulations. However, if you're going to imply that traditional SQL databases are non-performant in comparison, you may want to do a bit more looking at the performance numbers both PostgreSQL and MySQL are capable of.
100+ million transactions per day is pretty easy to achieve with a traditional SQL DB. Also, you can do a lot of filtering in software specialized for those use cases, reducing the need to consume processing time in the Node.js V8 thread.
I don't want to knock RethinkDB here, just point out that there are stronger performance cases to be made.
As mentioned by another user though, the filtering here is done entirely server-side (at RethinkDB's level), so the V8 thread performance isn't really a concern. https://news.ycombinator.com/item?id=9411738 for more info.
70 millions requests / week is actually very weak for a NoSQL database and should be left out of the promotion material.
Can someone explain the benefit of RethinkDB over MongoDB?
RethinkDB is based on a fundamentally different architecture from MongoDB. Instead of polling for changes, the developer can tell RethinkDB to continuously push updated query results in realtime -- check out http://rethinkdb.com/faq/ for more details on this.
Just FYI, Rethink does sharding and JavaScript queries (including callbacks) -- http://rethinkdb.com/api/javascript/js/. The `js` command interops with every other command in RethinkDB and works really well.
var signupFilter = new Date();
signupFilter.setDate(signupFilter.getDate()-30); // get a timestamp from 30 days ago
r.table('users').filter(function(user){
return user('signup_date').gt(signupFilter);
}).run(function(err, user){
// ... a cursor to stream through the data which can also be converted
// to an array using the toArray method
});
Is a lot nastier than: db.query('SELECT * FROM users WHERE signup_date > CURDATE() - INTERVAL 30 DAY;', {}, function (err, users) {
// Do stuff
});
No?However, what the former does that the latter does not is provide a mechanism to build up and modify queries. It can be very helpful to pass around and affect partial queries when you are looking to eliminate repetitive code for building multiple, similar queries.
This is probably why many abstraction layers have query builders that look a lot like the syntax that you call nasty to generate the 'less nasty' raw SQL.
Why can't the RethinkDB abstraction layer just be better? Why isn't:
var dateFilter = new Date();
dateFilter = dateFilter.setDate(dateFilter.getDate() - 30);
rdb.table('users').get([ { column: signup_date, gt: dateFilter } ]).each(function (err, user) {
// Do stuff
});
Possible? That's just off the top of my head how I would do it in a way that's native JS and far better than what's presented in the article.I'm also a bit wary of trying to introduce too much 'magic' just to make things convenient.
r.table('users').filter(r.row('signup_date').gt(signupFilter)).run()
Using an anonymous function like in the first example is optional. `r.row` can be very convenient. In this case, you only need to use `r.row` because you're using the `gt` comparison. If you're just doing a direct match, you can use this syntax: r.table('users').filter({signup_date: dateFilter})I'm curious to see someone try integrating RethinkDB with Meteor.
[{'first_name':'mike'},{'first_name':bill'},...]
vs
{meta: {'header':['first_name']]}, data: [['mike'],['bill],...]};
This is why I can't consider databases like RethinkDB or Mongo. They are taking such a big hit already for using something like BSON as a storage that I don't even want to be involved in that train of thought anymore.
Whenever I see one of those "awesome" no-SQL queries, I can't help but think about how ugly and bulky they are compared to SQL.
Or compared knex.js for node:
select().from('users').where('signup_date', '>', signupFilter)
It supports promises. What's wrong with that?
// plugins/replicate.js
var replicator = require('replicator');
module.exports = exports = function replicatePlugin (schema, options) {
schema.pre('save', function (next) {
// notify subscribers of save
replicator.notify('save', this);
next();
});
}
// schemas/game.js
var replicatePlugin = require('../plugins/replicate.js');
var GameSchema = new Schema({ ... });
GameSchema.plugin(replicatePlugin);RethinkDB also lets you write queries and subscribe to changes on the query itself. So in mongo, you can tail the replication oplog to avoid polling, but you still need to filter every event happening on the database for the ones you're interested in. On top of that, if you need to do transformations of the data, you have to re-apply them to what you get from the oplog. With RethinkDB, you write the same query you would have, and the database can be very efficient in only sending changes you're actually interested in, and send them with the transformations you asked to be applied.
Check out these slides if you're interested: http://deontologician.github.io/node_talk/#/
r.table('users').filter(function(user){return user('signup_date').gt(signupFilter);}).run(...
is running this filter in the database, not in node?They key line(s) is/are:
Predicates to filter are evaluated on the server, and must use ReQL expressions. You cannot use standard JavaScript comparison operators such as ==, </> and ||/&&.
It's essentially equivalent to:
r.table('users').filter(r.row("signup_date").gt(signupFilter)).run(conn, callback);